uboot/drivers/i2c/designware_i2c_pci.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * (C) Copyright 2009
   4 * Vipin Kumar, ST Micoelectronics, vipin.kumar@st.com.
   5 * Copyright 2019 Google Inc
   6 */
   7
   8#include <common.h>
   9#include <dm.h>
  10#include <log.h>
  11#include <spl.h>
  12#include <acpi/acpigen.h>
  13#include <acpi/acpi_device.h>
  14#include <asm/lpss.h>
  15#include <dm/acpi.h>
  16#include <dm/device-internal.h>
  17#include <dm/uclass-internal.h>
  18#include "designware_i2c.h"
  19
  20enum {
  21        VANILLA         = 0,    /* standard I2C with no tweaks */
  22        INTEL_APL,              /* Apollo Lake I2C */
  23};
  24
  25/* BayTrail HCNT/LCNT/SDA hold time */
  26static struct dw_scl_sda_cfg byt_config = {
  27        .ss_hcnt = 0x200,
  28        .fs_hcnt = 0x55,
  29        .ss_lcnt = 0x200,
  30        .fs_lcnt = 0x99,
  31        .sda_hold = 0x6,
  32};
  33
  34/* Have a weak function for now - possibly should be a new uclass */
  35__weak void lpss_reset_release(void *regs);
  36
  37static int designware_i2c_pci_of_to_plat(struct udevice *dev)
  38{
  39        struct dw_i2c *priv = dev_get_priv(dev);
  40
  41        if (spl_phase() < PHASE_SPL) {
  42                u32 base;
  43                int ret;
  44
  45                ret = dev_read_u32(dev, "early-regs", &base);
  46                if (ret)
  47                        return log_msg_ret("early-regs", ret);
  48
  49                /* Set i2c base address */
  50                dm_pci_write_config32(dev, PCI_BASE_ADDRESS_0, base);
  51
  52                /* Enable memory access and bus master */
  53                dm_pci_write_config32(dev, PCI_COMMAND, PCI_COMMAND_MEMORY |
  54                                      PCI_COMMAND_MASTER);
  55        }
  56
  57        if (spl_phase() < PHASE_BOARD_F) {
  58                /* Handle early, fixed mapping into a different address space */
  59                priv->regs = (struct i2c_regs *)dm_pci_read_bar32(dev, 0);
  60        } else {
  61                priv->regs = (struct i2c_regs *)
  62                        dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, PCI_REGION_MEM);
  63        }
  64        if (!priv->regs)
  65                return -EINVAL;
  66
  67        /* Save base address from PCI BAR */
  68        if (IS_ENABLED(CONFIG_INTEL_BAYTRAIL))
  69                /* Use BayTrail specific timing values */
  70                priv->scl_sda_cfg = &byt_config;
  71        if (dev_get_driver_data(dev) == INTEL_APL)
  72                priv->has_spk_cnt = true;
  73
  74        return designware_i2c_of_to_plat(dev);
  75}
  76
  77static int designware_i2c_pci_probe(struct udevice *dev)
  78{
  79        struct dw_i2c *priv = dev_get_priv(dev);
  80
  81        if (dev_get_driver_data(dev) == INTEL_APL) {
  82                /* Ensure controller is in D0 state */
  83                lpss_set_power_state(dev, STATE_D0);
  84
  85                lpss_reset_release(priv->regs);
  86        }
  87
  88        return designware_i2c_probe(dev);
  89}
  90
  91static int designware_i2c_pci_bind(struct udevice *dev)
  92{
  93        char name[20];
  94
  95        if (dev_has_ofnode(dev))
  96                return 0;
  97
  98        sprintf(name, "i2c_designware#%u", dev_seq(dev));
  99        device_set_name(dev, name);
 100
 101        return 0;
 102}
 103
 104/*
 105 * Write ACPI object to describe speed configuration.
 106 *
 107 * ACPI Object: Name ("xxxx", Package () { scl_lcnt, scl_hcnt, sda_hold }
 108 *
 109 * SSCN: I2C_SPEED_STANDARD
 110 * FMCN: I2C_SPEED_FAST
 111 * FPCN: I2C_SPEED_FAST_PLUS
 112 * HSCN: I2C_SPEED_HIGH
 113 */
 114static void dw_i2c_acpi_write_speed_config(struct acpi_ctx *ctx,
 115                                           struct dw_i2c_speed_config *config)
 116{
 117        switch (config->speed_mode) {
 118        case IC_SPEED_MODE_HIGH:
 119                acpigen_write_name(ctx, "HSCN");
 120                break;
 121        case IC_SPEED_MODE_FAST_PLUS:
 122                acpigen_write_name(ctx, "FPCN");
 123                break;
 124        case IC_SPEED_MODE_FAST:
 125                acpigen_write_name(ctx, "FMCN");
 126                break;
 127        case IC_SPEED_MODE_STANDARD:
 128        default:
 129                acpigen_write_name(ctx, "SSCN");
 130        }
 131
 132        /* Package () { scl_lcnt, scl_hcnt, sda_hold } */
 133        acpigen_write_package(ctx, 3);
 134        acpigen_write_word(ctx, config->scl_hcnt);
 135        acpigen_write_word(ctx, config->scl_lcnt);
 136        acpigen_write_dword(ctx, config->sda_hold);
 137        acpigen_pop_len(ctx);
 138}
 139
 140/*
 141 * Generate I2C timing information into the SSDT for the OS driver to consume,
 142 * optionally applying override values provided by the caller.
 143 */
 144static int dw_i2c_acpi_fill_ssdt(const struct udevice *dev,
 145                                 struct acpi_ctx *ctx)
 146{
 147        struct dw_i2c_speed_config config;
 148        char path[ACPI_PATH_MAX];
 149        u32 speeds[4];
 150        uint speed;
 151        int size;
 152        int ret;
 153
 154        /* If no device-tree node, ignore this since we assume it isn't used */
 155        if (!dev_has_ofnode(dev))
 156                return 0;
 157
 158        ret = acpi_device_path(dev, path, sizeof(path));
 159        if (ret)
 160                return log_msg_ret("path", ret);
 161
 162        size = dev_read_size(dev, "i2c,speeds");
 163        if (size < 0)
 164                return log_msg_ret("i2c,speeds", -EINVAL);
 165
 166        size /= sizeof(u32);
 167        if (size > ARRAY_SIZE(speeds))
 168                return log_msg_ret("array", -E2BIG);
 169
 170        ret = dev_read_u32_array(dev, "i2c,speeds", speeds, size);
 171        if (ret)
 172                return log_msg_ret("read", -E2BIG);
 173
 174        speed = dev_read_u32_default(dev, "clock-frequency", 100000);
 175        acpigen_write_scope(ctx, path);
 176        ret = dw_i2c_gen_speed_config(dev, speed, &config);
 177        if (ret)
 178                return log_msg_ret("config", ret);
 179        dw_i2c_acpi_write_speed_config(ctx, &config);
 180        acpigen_pop_len(ctx);
 181
 182        return 0;
 183}
 184
 185struct acpi_ops dw_i2c_acpi_ops = {
 186        .fill_ssdt      = dw_i2c_acpi_fill_ssdt,
 187};
 188
 189static const struct udevice_id designware_i2c_pci_ids[] = {
 190        { .compatible = "snps,designware-i2c-pci" },
 191        { .compatible = "intel,apl-i2c", .data = INTEL_APL },
 192        { }
 193};
 194
 195DM_DRIVER_ALIAS(i2c_designware_pci, intel_apl_i2c)
 196
 197U_BOOT_DRIVER(i2c_designware_pci) = {
 198        .name   = "i2c_designware_pci",
 199        .id     = UCLASS_I2C,
 200        .of_match = designware_i2c_pci_ids,
 201        .bind   = designware_i2c_pci_bind,
 202        .of_to_plat     = designware_i2c_pci_of_to_plat,
 203        .probe  = designware_i2c_pci_probe,
 204        .priv_auto      = sizeof(struct dw_i2c),
 205        .remove = designware_i2c_remove,
 206        .flags = DM_FLAG_OS_PREPARE,
 207        .ops    = &designware_i2c_ops,
 208        ACPI_OPS_PTR(&dw_i2c_acpi_ops)
 209};
 210
 211static struct pci_device_id designware_pci_supported[] = {
 212        /* Intel BayTrail has 7 I2C controller located on the PCI bus */
 213        { PCI_VDEVICE(INTEL, 0x0f41) },
 214        { PCI_VDEVICE(INTEL, 0x0f42) },
 215        { PCI_VDEVICE(INTEL, 0x0f43) },
 216        { PCI_VDEVICE(INTEL, 0x0f44) },
 217        { PCI_VDEVICE(INTEL, 0x0f45) },
 218        { PCI_VDEVICE(INTEL, 0x0f46) },
 219        { PCI_VDEVICE(INTEL, 0x0f47) },
 220        { PCI_VDEVICE(INTEL, 0x5aac), .driver_data = INTEL_APL },
 221        { PCI_VDEVICE(INTEL, 0x5aae), .driver_data = INTEL_APL },
 222        { PCI_VDEVICE(INTEL, 0x5ab0), .driver_data = INTEL_APL },
 223        { PCI_VDEVICE(INTEL, 0x5ab2), .driver_data = INTEL_APL },
 224        { PCI_VDEVICE(INTEL, 0x5ab4), .driver_data = INTEL_APL },
 225        { PCI_VDEVICE(INTEL, 0x5ab6), .driver_data = INTEL_APL },
 226        {},
 227};
 228
 229U_BOOT_PCI_DEVICE(i2c_designware_pci, designware_pci_supported);
 230