diff options
-rw-r--r-- | drivers/acpi/acpi_lpss.c | 125 | ||||
-rw-r--r-- | drivers/clk/x86/clk-lpt.c | 4 |
2 files changed, 116 insertions, 13 deletions
diff --git a/drivers/acpi/acpi_lpss.c b/drivers/acpi/acpi_lpss.c index cab13f2fc28e..6a382188fa20 100644 --- a/drivers/acpi/acpi_lpss.c +++ b/drivers/acpi/acpi_lpss.c | |||
@@ -32,12 +32,26 @@ ACPI_MODULE_NAME("acpi_lpss"); | |||
32 | #define LPSS_GENERAL_LTR_MODE_SW BIT(2) | 32 | #define LPSS_GENERAL_LTR_MODE_SW BIT(2) |
33 | #define LPSS_SW_LTR 0x10 | 33 | #define LPSS_SW_LTR 0x10 |
34 | #define LPSS_AUTO_LTR 0x14 | 34 | #define LPSS_AUTO_LTR 0x14 |
35 | #define LPSS_TX_INT 0x20 | ||
36 | #define LPSS_TX_INT_MASK BIT(1) | ||
37 | |||
38 | struct lpss_shared_clock { | ||
39 | const char *name; | ||
40 | unsigned long rate; | ||
41 | struct clk *clk; | ||
42 | }; | ||
43 | |||
44 | struct lpss_private_data; | ||
35 | 45 | ||
36 | struct lpss_device_desc { | 46 | struct lpss_device_desc { |
37 | bool clk_required; | 47 | bool clk_required; |
38 | const char *clkdev_name; | 48 | const char *clkdev_name; |
39 | bool ltr_required; | 49 | bool ltr_required; |
40 | unsigned int prv_offset; | 50 | unsigned int prv_offset; |
51 | size_t prv_size_override; | ||
52 | bool clk_gate; | ||
53 | struct lpss_shared_clock *shared_clock; | ||
54 | void (*setup)(struct lpss_private_data *pdata); | ||
41 | }; | 55 | }; |
42 | 56 | ||
43 | static struct lpss_device_desc lpss_dma_desc = { | 57 | static struct lpss_device_desc lpss_dma_desc = { |
@@ -52,17 +66,76 @@ struct lpss_private_data { | |||
52 | const struct lpss_device_desc *dev_desc; | 66 | const struct lpss_device_desc *dev_desc; |
53 | }; | 67 | }; |
54 | 68 | ||
69 | static void lpss_uart_setup(struct lpss_private_data *pdata) | ||
70 | { | ||
71 | unsigned int tx_int_offset = pdata->dev_desc->prv_offset + LPSS_TX_INT; | ||
72 | u32 reg; | ||
73 | |||
74 | reg = readl(pdata->mmio_base + tx_int_offset); | ||
75 | writel(reg | LPSS_TX_INT_MASK, pdata->mmio_base + tx_int_offset); | ||
76 | } | ||
77 | |||
55 | static struct lpss_device_desc lpt_dev_desc = { | 78 | static struct lpss_device_desc lpt_dev_desc = { |
56 | .clk_required = true, | 79 | .clk_required = true, |
57 | .prv_offset = 0x800, | 80 | .prv_offset = 0x800, |
58 | .ltr_required = true, | 81 | .ltr_required = true, |
82 | .clk_gate = true, | ||
83 | }; | ||
84 | |||
85 | static struct lpss_device_desc lpt_uart_dev_desc = { | ||
86 | .clk_required = true, | ||
87 | .prv_offset = 0x800, | ||
88 | .ltr_required = true, | ||
89 | .clk_gate = true, | ||
90 | .setup = lpss_uart_setup, | ||
59 | }; | 91 | }; |
60 | 92 | ||
61 | static struct lpss_device_desc lpt_sdio_dev_desc = { | 93 | static struct lpss_device_desc lpt_sdio_dev_desc = { |
62 | .prv_offset = 0x1000, | 94 | .prv_offset = 0x1000, |
95 | .prv_size_override = 0x1018, | ||
63 | .ltr_required = true, | 96 | .ltr_required = true, |
64 | }; | 97 | }; |
65 | 98 | ||
99 | static struct lpss_shared_clock uart_clock = { | ||
100 | .name = "uart_clk", | ||
101 | .rate = 44236800, | ||
102 | }; | ||
103 | |||
104 | static struct lpss_device_desc byt_uart_dev_desc = { | ||
105 | .clk_required = true, | ||
106 | .prv_offset = 0x800, | ||
107 | .clk_gate = true, | ||
108 | .shared_clock = &uart_clock, | ||
109 | .setup = lpss_uart_setup, | ||
110 | }; | ||
111 | |||
112 | static struct lpss_shared_clock spi_clock = { | ||
113 | .name = "spi_clk", | ||
114 | .rate = 50000000, | ||
115 | }; | ||
116 | |||
117 | static struct lpss_device_desc byt_spi_dev_desc = { | ||
118 | .clk_required = true, | ||
119 | .prv_offset = 0x400, | ||
120 | .clk_gate = true, | ||
121 | .shared_clock = &spi_clock, | ||
122 | }; | ||
123 | |||
124 | static struct lpss_device_desc byt_sdio_dev_desc = { | ||
125 | .clk_required = true, | ||
126 | }; | ||
127 | |||
128 | static struct lpss_shared_clock i2c_clock = { | ||
129 | .name = "i2c_clk", | ||
130 | .rate = 100000000, | ||
131 | }; | ||
132 | |||
133 | static struct lpss_device_desc byt_i2c_dev_desc = { | ||
134 | .clk_required = true, | ||
135 | .prv_offset = 0x800, | ||
136 | .shared_clock = &i2c_clock, | ||
137 | }; | ||
138 | |||
66 | static const struct acpi_device_id acpi_lpss_device_ids[] = { | 139 | static const struct acpi_device_id acpi_lpss_device_ids[] = { |
67 | /* Generic LPSS devices */ | 140 | /* Generic LPSS devices */ |
68 | { "INTL9C60", (unsigned long)&lpss_dma_desc }, | 141 | { "INTL9C60", (unsigned long)&lpss_dma_desc }, |
@@ -72,11 +145,18 @@ static const struct acpi_device_id acpi_lpss_device_ids[] = { | |||
72 | { "INT33C1", (unsigned long)&lpt_dev_desc }, | 145 | { "INT33C1", (unsigned long)&lpt_dev_desc }, |
73 | { "INT33C2", (unsigned long)&lpt_dev_desc }, | 146 | { "INT33C2", (unsigned long)&lpt_dev_desc }, |
74 | { "INT33C3", (unsigned long)&lpt_dev_desc }, | 147 | { "INT33C3", (unsigned long)&lpt_dev_desc }, |
75 | { "INT33C4", (unsigned long)&lpt_dev_desc }, | 148 | { "INT33C4", (unsigned long)&lpt_uart_dev_desc }, |
76 | { "INT33C5", (unsigned long)&lpt_dev_desc }, | 149 | { "INT33C5", (unsigned long)&lpt_uart_dev_desc }, |
77 | { "INT33C6", (unsigned long)&lpt_sdio_dev_desc }, | 150 | { "INT33C6", (unsigned long)&lpt_sdio_dev_desc }, |
78 | { "INT33C7", }, | 151 | { "INT33C7", }, |
79 | 152 | ||
153 | /* BayTrail LPSS devices */ | ||
154 | { "80860F0A", (unsigned long)&byt_uart_dev_desc }, | ||
155 | { "80860F0E", (unsigned long)&byt_spi_dev_desc }, | ||
156 | { "80860F14", (unsigned long)&byt_sdio_dev_desc }, | ||
157 | { "80860F41", (unsigned long)&byt_i2c_dev_desc }, | ||
158 | { "INT33B2", }, | ||
159 | |||
80 | { } | 160 | { } |
81 | }; | 161 | }; |
82 | 162 | ||
@@ -98,7 +178,10 @@ static int register_device_clock(struct acpi_device *adev, | |||
98 | struct lpss_private_data *pdata) | 178 | struct lpss_private_data *pdata) |
99 | { | 179 | { |
100 | const struct lpss_device_desc *dev_desc = pdata->dev_desc; | 180 | const struct lpss_device_desc *dev_desc = pdata->dev_desc; |
181 | struct lpss_shared_clock *shared_clock = dev_desc->shared_clock; | ||
182 | struct clk *clk = ERR_PTR(-ENODEV); | ||
101 | struct lpss_clk_data *clk_data; | 183 | struct lpss_clk_data *clk_data; |
184 | const char *parent; | ||
102 | 185 | ||
103 | if (!lpss_clk_dev) | 186 | if (!lpss_clk_dev) |
104 | lpt_register_clock_device(); | 187 | lpt_register_clock_device(); |
@@ -117,14 +200,30 @@ static int register_device_clock(struct acpi_device *adev, | |||
117 | || pdata->mmio_size < dev_desc->prv_offset + LPSS_CLK_SIZE) | 200 | || pdata->mmio_size < dev_desc->prv_offset + LPSS_CLK_SIZE) |
118 | return -ENODATA; | 201 | return -ENODATA; |
119 | 202 | ||
120 | pdata->clk = clk_register_gate(NULL, dev_name(&adev->dev), | 203 | parent = clk_data->name; |
121 | clk_data->name, 0, | 204 | |
122 | pdata->mmio_base + dev_desc->prv_offset, | 205 | if (shared_clock) { |
123 | 0, 0, NULL); | 206 | clk = shared_clock->clk; |
124 | if (IS_ERR(pdata->clk)) | 207 | if (!clk) { |
125 | return PTR_ERR(pdata->clk); | 208 | clk = clk_register_fixed_rate(NULL, shared_clock->name, |
209 | "lpss_clk", 0, | ||
210 | shared_clock->rate); | ||
211 | shared_clock->clk = clk; | ||
212 | } | ||
213 | parent = shared_clock->name; | ||
214 | } | ||
215 | |||
216 | if (dev_desc->clk_gate) { | ||
217 | clk = clk_register_gate(NULL, dev_name(&adev->dev), parent, 0, | ||
218 | pdata->mmio_base + dev_desc->prv_offset, | ||
219 | 0, 0, NULL); | ||
220 | pdata->clk = clk; | ||
221 | } | ||
126 | 222 | ||
127 | clk_register_clkdev(pdata->clk, NULL, dev_name(&adev->dev)); | 223 | if (IS_ERR(clk)) |
224 | return PTR_ERR(clk); | ||
225 | |||
226 | clk_register_clkdev(clk, NULL, dev_name(&adev->dev)); | ||
128 | return 0; | 227 | return 0; |
129 | } | 228 | } |
130 | 229 | ||
@@ -152,7 +251,10 @@ static int acpi_lpss_create_device(struct acpi_device *adev, | |||
152 | 251 | ||
153 | list_for_each_entry(rentry, &resource_list, node) | 252 | list_for_each_entry(rentry, &resource_list, node) |
154 | if (resource_type(&rentry->res) == IORESOURCE_MEM) { | 253 | if (resource_type(&rentry->res) == IORESOURCE_MEM) { |
155 | pdata->mmio_size = resource_size(&rentry->res); | 254 | if (dev_desc->prv_size_override) |
255 | pdata->mmio_size = dev_desc->prv_size_override; | ||
256 | else | ||
257 | pdata->mmio_size = resource_size(&rentry->res); | ||
156 | pdata->mmio_base = ioremap(rentry->res.start, | 258 | pdata->mmio_base = ioremap(rentry->res.start, |
157 | pdata->mmio_size); | 259 | pdata->mmio_size); |
158 | pdata->dev_desc = dev_desc; | 260 | pdata->dev_desc = dev_desc; |
@@ -182,6 +284,9 @@ static int acpi_lpss_create_device(struct acpi_device *adev, | |||
182 | goto err_out; | 284 | goto err_out; |
183 | } | 285 | } |
184 | 286 | ||
287 | if (dev_desc->setup) | ||
288 | dev_desc->setup(pdata); | ||
289 | |||
185 | adev->driver_data = pdata; | 290 | adev->driver_data = pdata; |
186 | ret = acpi_create_platform_device(adev, id); | 291 | ret = acpi_create_platform_device(adev, id); |
187 | if (ret > 0) | 292 | if (ret > 0) |
diff --git a/drivers/clk/x86/clk-lpt.c b/drivers/clk/x86/clk-lpt.c index 4f45eee9e33b..812f83f8b0c6 100644 --- a/drivers/clk/x86/clk-lpt.c +++ b/drivers/clk/x86/clk-lpt.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Intel Lynxpoint LPSS clocks. | 2 | * Intel Low Power Subsystem clocks. |
3 | * | 3 | * |
4 | * Copyright (C) 2013, Intel Corporation | 4 | * Copyright (C) 2013, Intel Corporation |
5 | * Authors: Mika Westerberg <mika.westerberg@linux.intel.com> | 5 | * Authors: Mika Westerberg <mika.westerberg@linux.intel.com> |
@@ -18,8 +18,6 @@ | |||
18 | #include <linux/platform_data/clk-lpss.h> | 18 | #include <linux/platform_data/clk-lpss.h> |
19 | #include <linux/platform_device.h> | 19 | #include <linux/platform_device.h> |
20 | 20 | ||
21 | #define PRV_CLOCK_PARAMS 0x800 | ||
22 | |||
23 | static int lpt_clk_probe(struct platform_device *pdev) | 21 | static int lpt_clk_probe(struct platform_device *pdev) |
24 | { | 22 | { |
25 | struct lpss_clk_data *drvdata; | 23 | struct lpss_clk_data *drvdata; |