struct lpss_device_desc {
bool clk_required;
- const char *clk_parent;
+ const char *clkdev_name;
bool ltr_required;
unsigned int prv_offset;
};
+static struct lpss_device_desc lpss_dma_desc = {
+ .clk_required = true,
+ .clkdev_name = "hclk",
+};
+
struct lpss_private_data {
void __iomem *mmio_base;
resource_size_t mmio_size;
static struct lpss_device_desc lpt_dev_desc = {
.clk_required = true,
- .clk_parent = "lpss_clk",
.prv_offset = 0x800,
.ltr_required = true,
};
};
static const struct acpi_device_id acpi_lpss_device_ids[] = {
+ /* Generic LPSS devices */
+ { "INTL9C60", (unsigned long)&lpss_dma_desc },
+
/* Lynxpoint LPSS devices */
{ "INT33C0", (unsigned long)&lpt_dev_desc },
{ "INT33C1", (unsigned long)&lpt_dev_desc },
struct lpss_private_data *pdata)
{
const struct lpss_device_desc *dev_desc = pdata->dev_desc;
+ struct lpss_clk_data *clk_data;
if (!lpss_clk_dev)
lpt_register_clock_device();
- if (!dev_desc->clk_parent || !pdata->mmio_base
+ clk_data = platform_get_drvdata(lpss_clk_dev);
+ if (!clk_data)
+ return -ENODEV;
+
+ if (dev_desc->clkdev_name) {
+ clk_register_clkdev(clk_data->clk, dev_desc->clkdev_name,
+ dev_name(&adev->dev));
+ return 0;
+ }
+
+ if (!pdata->mmio_base
|| pdata->mmio_size < dev_desc->prv_offset + LPSS_CLK_SIZE)
return -ENODATA;
pdata->clk = clk_register_gate(NULL, dev_name(&adev->dev),
- dev_desc->clk_parent, 0,
+ clk_data->name, 0,
pdata->mmio_base + dev_desc->prv_offset,
0, 0, NULL);
if (IS_ERR(pdata->clk))
pdata->mmio_size = resource_size(&rentry->res);
pdata->mmio_base = ioremap(rentry->res.start,
pdata->mmio_size);
- pdata->dev_desc = dev_desc;
break;
}
acpi_dev_free_resource_list(&resource_list);
+ pdata->dev_desc = dev_desc;
+
if (dev_desc->clk_required) {
ret = register_device_clock(adev, pdata);
if (ret) {
- /*
- * Skip the device, but don't terminate the namespace
- * scan.
- */
- kfree(pdata);
- return 0;
+ /* Skip the device, but continue the namespace scan. */
+ ret = 0;
+ goto err_out;
}
}
+ /*
+ * This works around a known issue in ACPI tables where LPSS devices
+ * have _PS0 and _PS3 without _PSC (and no power resources), so
+ * acpi_bus_init_power() will assume that the BIOS has put them into D0.
+ */
+ ret = acpi_device_fix_up_power(adev);
+ if (ret) {
+ /* Skip the device, but continue the namespace scan. */
+ ret = 0;
+ goto err_out;
+ }
+
adev->driver_data = pdata;
ret = acpi_create_platform_device(adev, id);
if (ret > 0)