diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-06-11 18:15:22 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-06-11 18:15:22 -0700 |
commit | 32bcbf8b6d09428907fd045a4ea90562ec7dc4a2 (patch) | |
tree | 5fe094aa94931f207307817c747fcc5935e2665c /drivers/bus | |
parent | 721afaa2aeb860067decdddadc84ed16f42f2048 (diff) | |
parent | 32561354b16944e784e82a2011765c50e77e1c56 (diff) | |
download | linux-32bcbf8b6d09428907fd045a4ea90562ec7dc4a2.tar.gz linux-32bcbf8b6d09428907fd045a4ea90562ec7dc4a2.tar.bz2 linux-32bcbf8b6d09428907fd045a4ea90562ec7dc4a2.zip |
Merge tag 'armsoc-drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
Pull ARM SoC driver updates from Olof Johansson:
"This contains platform-related driver updates for ARM and ARM64.
Highlights:
- ARM SCMI (System Control & Management Interface) driver cleanups
- Hisilicon support for LPC bus w/ ACPI
- Reset driver updates for several platforms: Uniphier,
- Rockchip power domain bindings and hardware descriptions for
several SoCs.
- Tegra memory controller reset improvements"
* tag 'armsoc-drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (59 commits)
ARM: tegra: fix compile-testing PCI host driver
soc: rockchip: power-domain: add power domain support for px30
dt-bindings: power: add binding for px30 power domains
dt-bindings: power: add PX30 SoCs header for power-domain
soc: rockchip: power-domain: add power domain support for rk3228
dt-bindings: power: add binding for rk3228 power domains
dt-bindings: power: add RK3228 SoCs header for power-domain
soc: rockchip: power-domain: add power domain support for rk3128
dt-bindings: power: add binding for rk3128 power domains
dt-bindings: power: add RK3128 SoCs header for power-domain
soc: rockchip: power-domain: add power domain support for rk3036
dt-bindings: power: add binding for rk3036 power domains
dt-bindings: power: add RK3036 SoCs header for power-domain
dt-bindings: memory: tegra: Remove Tegra114 SATA and AFI reset definitions
memory: tegra: Remove Tegra114 SATA and AFI reset definitions
memory: tegra: Register SMMU after MC driver became ready
soc: mediatek: remove unneeded semicolon
soc: mediatek: add a fixed wait for SRAM stable
soc: mediatek: introduce a CAPS flag for scp_domain_data
soc: mediatek: reuse regmap_read_poll_timeout helpers
...
Diffstat (limited to 'drivers/bus')
-rw-r--r-- | drivers/bus/Kconfig | 1 | ||||
-rw-r--r-- | drivers/bus/arm-cci.c | 2 | ||||
-rw-r--r-- | drivers/bus/hisi_lpc.c | 159 |
3 files changed, 97 insertions, 65 deletions
diff --git a/drivers/bus/Kconfig b/drivers/bus/Kconfig index 6dc177bf4c42..d1c0b60e9326 100644 --- a/drivers/bus/Kconfig +++ b/drivers/bus/Kconfig @@ -33,7 +33,6 @@ config HISILICON_LPC bool "Support for ISA I/O space on HiSilicon Hip06/7" depends on ARM64 && (ARCH_HISI || COMPILE_TEST) select INDIRECT_PIO - select MFD_CORE if ACPI help Driver to enable I/O access to devices attached to the Low Pin Count bus on the HiSilicon Hip06/7 SoC. diff --git a/drivers/bus/arm-cci.c b/drivers/bus/arm-cci.c index 443e4c3fd357..b8184a903583 100644 --- a/drivers/bus/arm-cci.c +++ b/drivers/bus/arm-cci.c @@ -371,8 +371,6 @@ asmlinkage void __naked cci_enable_port_for_self(void) [sizeof_struct_cpu_port] "i" (sizeof(struct cpu_port)), [sizeof_struct_ace_port] "i" (sizeof(struct cci_ace_port)), [offsetof_port_phys] "i" (offsetof(struct cci_ace_port, phys)) ); - - unreachable(); } /** diff --git a/drivers/bus/hisi_lpc.c b/drivers/bus/hisi_lpc.c index 2d4611e4c339..d5f85455fa62 100644 --- a/drivers/bus/hisi_lpc.c +++ b/drivers/bus/hisi_lpc.c @@ -11,12 +11,12 @@ #include <linux/delay.h> #include <linux/io.h> #include <linux/logic_pio.h> -#include <linux/mfd/core.h> #include <linux/module.h> #include <linux/of.h> #include <linux/of_address.h> #include <linux/of_platform.h> #include <linux/pci.h> +#include <linux/serial_8250.h> #include <linux/slab.h> #define DRV_NAME "hisi-lpc" @@ -341,15 +341,6 @@ static const struct logic_pio_host_ops hisi_lpc_ops = { }; #ifdef CONFIG_ACPI -#define MFD_CHILD_NAME_PREFIX DRV_NAME"-" -#define MFD_CHILD_NAME_LEN (ACPI_ID_LEN + sizeof(MFD_CHILD_NAME_PREFIX) - 1) - -struct hisi_lpc_mfd_cell { - struct mfd_cell_acpi_match acpi_match; - char name[MFD_CHILD_NAME_LEN]; - char pnpid[ACPI_ID_LEN]; -}; - static int hisi_lpc_acpi_xlat_io_res(struct acpi_device *adev, struct acpi_device *host, struct resource *res) @@ -368,7 +359,7 @@ static int hisi_lpc_acpi_xlat_io_res(struct acpi_device *adev, } /* - * hisi_lpc_acpi_set_io_res - set the resources for a child's MFD + * hisi_lpc_acpi_set_io_res - set the resources for a child * @child: the device node to be updated the I/O resource * @hostdev: the device node associated with host controller * @res: double pointer to be set to the address of translated resources @@ -452,78 +443,122 @@ static int hisi_lpc_acpi_set_io_res(struct device *child, return 0; } +static int hisi_lpc_acpi_remove_subdev(struct device *dev, void *unused) +{ + platform_device_unregister(to_platform_device(dev)); + return 0; +} + +struct hisi_lpc_acpi_cell { + const char *hid; + const char *name; + void *pdata; + size_t pdata_size; +}; + /* * hisi_lpc_acpi_probe - probe children for ACPI FW * @hostdev: LPC host device pointer * * Returns 0 when successful, and a negative value for failure. * - * Scan all child devices and create a per-device MFD with - * logical PIO translated IO resources. + * Create a platform device per child, fixing up the resources + * from bus addresses to Logical PIO addresses. + * */ static int hisi_lpc_acpi_probe(struct device *hostdev) { struct acpi_device *adev = ACPI_COMPANION(hostdev); - struct hisi_lpc_mfd_cell *hisi_lpc_mfd_cells; - struct mfd_cell *mfd_cells; struct acpi_device *child; - int size, ret, count = 0, cell_num = 0; - - list_for_each_entry(child, &adev->children, node) - cell_num++; - - /* allocate the mfd cell and companion ACPI info, one per child */ - size = sizeof(*mfd_cells) + sizeof(*hisi_lpc_mfd_cells); - mfd_cells = devm_kcalloc(hostdev, cell_num, size, GFP_KERNEL); - if (!mfd_cells) - return -ENOMEM; + int ret; - hisi_lpc_mfd_cells = (struct hisi_lpc_mfd_cell *)&mfd_cells[cell_num]; /* Only consider the children of the host */ list_for_each_entry(child, &adev->children, node) { - struct mfd_cell *mfd_cell = &mfd_cells[count]; - struct hisi_lpc_mfd_cell *hisi_lpc_mfd_cell = - &hisi_lpc_mfd_cells[count]; - struct mfd_cell_acpi_match *acpi_match = - &hisi_lpc_mfd_cell->acpi_match; - char *name = hisi_lpc_mfd_cell[count].name; - char *pnpid = hisi_lpc_mfd_cell[count].pnpid; - struct mfd_cell_acpi_match match = { - .pnpid = pnpid, + const char *hid = acpi_device_hid(child); + const struct hisi_lpc_acpi_cell *cell; + struct platform_device *pdev; + const struct resource *res; + bool found = false; + int num_res; + + ret = hisi_lpc_acpi_set_io_res(&child->dev, &adev->dev, &res, + &num_res); + if (ret) { + dev_warn(hostdev, "set resource fail (%d)\n", ret); + goto fail; + } + + cell = (struct hisi_lpc_acpi_cell []){ + /* ipmi */ + { + .hid = "IPI0001", + .name = "hisi-lpc-ipmi", + }, + /* 8250-compatible uart */ + { + .hid = "HISI1031", + .name = "serial8250", + .pdata = (struct plat_serial8250_port []) { + { + .iobase = res->start, + .uartclk = 1843200, + .iotype = UPIO_PORT, + .flags = UPF_BOOT_AUTOCONF, + }, + {} + }, + .pdata_size = 2 * + sizeof(struct plat_serial8250_port), + }, + {} }; - /* - * For any instances of this host controller (Hip06 and Hip07 - * are the only chipsets), we would not have multiple slaves - * with the same HID. And in any system we would have just one - * controller active. So don't worrry about MFD name clashes. - */ - snprintf(name, MFD_CHILD_NAME_LEN, MFD_CHILD_NAME_PREFIX"%s", - acpi_device_hid(child)); - snprintf(pnpid, ACPI_ID_LEN, "%s", acpi_device_hid(child)); - - memcpy(acpi_match, &match, sizeof(*acpi_match)); - mfd_cell->name = name; - mfd_cell->acpi_match = acpi_match; - - ret = hisi_lpc_acpi_set_io_res(&child->dev, &adev->dev, - &mfd_cell->resources, - &mfd_cell->num_resources); - if (ret) { - dev_warn(&child->dev, "set resource fail (%d)\n", ret); - return ret; + for (; cell && cell->name; cell++) { + if (!strcmp(cell->hid, hid)) { + found = true; + break; + } } - count++; - } - ret = mfd_add_devices(hostdev, PLATFORM_DEVID_NONE, - mfd_cells, cell_num, NULL, 0, NULL); - if (ret) { - dev_err(hostdev, "failed to add mfd cells (%d)\n", ret); - return ret; + if (!found) { + dev_warn(hostdev, + "could not find cell for child device (%s)\n", + hid); + ret = -ENODEV; + goto fail; + } + + pdev = platform_device_alloc(cell->name, PLATFORM_DEVID_AUTO); + if (!pdev) { + ret = -ENOMEM; + goto fail; + } + + pdev->dev.parent = hostdev; + ACPI_COMPANION_SET(&pdev->dev, child); + + ret = platform_device_add_resources(pdev, res, num_res); + if (ret) + goto fail; + + ret = platform_device_add_data(pdev, cell->pdata, + cell->pdata_size); + if (ret) + goto fail; + + ret = platform_device_add(pdev); + if (ret) + goto fail; + + acpi_device_set_enumerated(child); } return 0; + +fail: + device_for_each_child(hostdev, NULL, + hisi_lpc_acpi_remove_subdev); + return ret; } static const struct acpi_device_id hisi_lpc_acpi_match[] = { |