Skip to content

Commit ed3a872

Browse files
Heikki Krogerusrafaeljw
authored andcommitted
ACPI / LPSS: support for fractional divider clock
This creates fractional divider type clock for the ones that have it. It is needed by the UART driver as the clock rate must accommodate to the requested baud rate. Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
1 parent 5a3c7c0 commit ed3a872

File tree

1 file changed

+52
-23
lines changed

1 file changed

+52
-23
lines changed

drivers/acpi/acpi_lpss.c

Lines changed: 52 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ ACPI_MODULE_NAME("acpi_lpss");
2929
#define LPSS_LTR_SIZE 0x18
3030

3131
/* Offsets relative to LPSS_PRIVATE_OFFSET */
32+
#define LPSS_CLK_DIVIDER_DEF_MASK (BIT(1) | BIT(16))
3233
#define LPSS_GENERAL 0x08
3334
#define LPSS_GENERAL_LTR_MODE_SW BIT(2)
3435
#define LPSS_GENERAL_UART_RTS_OVRD BIT(3)
@@ -60,6 +61,7 @@ struct lpss_device_desc {
6061
bool ltr_required;
6162
unsigned int prv_offset;
6263
size_t prv_size_override;
64+
bool clk_divider;
6365
bool clk_gate;
6466
bool save_ctx;
6567
struct lpss_shared_clock *shared_clock;
@@ -94,6 +96,14 @@ static void lpss_uart_setup(struct lpss_private_data *pdata)
9496
}
9597

9698
static struct lpss_device_desc lpt_dev_desc = {
99+
.clk_required = true,
100+
.prv_offset = 0x800,
101+
.ltr_required = true,
102+
.clk_divider = true,
103+
.clk_gate = true,
104+
};
105+
106+
static struct lpss_device_desc lpt_i2c_dev_desc = {
97107
.clk_required = true,
98108
.prv_offset = 0x800,
99109
.ltr_required = true,
@@ -104,6 +114,7 @@ static struct lpss_device_desc lpt_uart_dev_desc = {
104114
.clk_required = true,
105115
.prv_offset = 0x800,
106116
.ltr_required = true,
117+
.clk_divider = true,
107118
.clk_gate = true,
108119
.setup = lpss_uart_setup,
109120
};
@@ -125,31 +136,21 @@ static struct lpss_device_desc byt_pwm_dev_desc = {
125136
.shared_clock = &pwm_clock,
126137
};
127138

128-
static struct lpss_shared_clock uart_clock = {
129-
.name = "uart_clk",
130-
.rate = 44236800,
131-
};
132-
133139
static struct lpss_device_desc byt_uart_dev_desc = {
134140
.clk_required = true,
135141
.prv_offset = 0x800,
142+
.clk_divider = true,
136143
.clk_gate = true,
137144
.save_ctx = true,
138-
.shared_clock = &uart_clock,
139145
.setup = lpss_uart_setup,
140146
};
141147

142-
static struct lpss_shared_clock spi_clock = {
143-
.name = "spi_clk",
144-
.rate = 50000000,
145-
};
146-
147148
static struct lpss_device_desc byt_spi_dev_desc = {
148149
.clk_required = true,
149150
.prv_offset = 0x400,
151+
.clk_divider = true,
150152
.clk_gate = true,
151153
.save_ctx = true,
152-
.shared_clock = &spi_clock,
153154
};
154155

155156
static struct lpss_device_desc byt_sdio_dev_desc = {
@@ -175,8 +176,8 @@ static const struct acpi_device_id acpi_lpss_device_ids[] = {
175176
/* Lynxpoint LPSS devices */
176177
{ "INT33C0", (unsigned long)&lpt_dev_desc },
177178
{ "INT33C1", (unsigned long)&lpt_dev_desc },
178-
{ "INT33C2", (unsigned long)&lpt_dev_desc },
179-
{ "INT33C3", (unsigned long)&lpt_dev_desc },
179+
{ "INT33C2", (unsigned long)&lpt_i2c_dev_desc },
180+
{ "INT33C3", (unsigned long)&lpt_i2c_dev_desc },
180181
{ "INT33C4", (unsigned long)&lpt_uart_dev_desc },
181182
{ "INT33C5", (unsigned long)&lpt_uart_dev_desc },
182183
{ "INT33C6", (unsigned long)&lpt_sdio_dev_desc },
@@ -192,8 +193,8 @@ static const struct acpi_device_id acpi_lpss_device_ids[] = {
192193

193194
{ "INT3430", (unsigned long)&lpt_dev_desc },
194195
{ "INT3431", (unsigned long)&lpt_dev_desc },
195-
{ "INT3432", (unsigned long)&lpt_dev_desc },
196-
{ "INT3433", (unsigned long)&lpt_dev_desc },
196+
{ "INT3432", (unsigned long)&lpt_i2c_dev_desc },
197+
{ "INT3433", (unsigned long)&lpt_i2c_dev_desc },
197198
{ "INT3434", (unsigned long)&lpt_uart_dev_desc },
198199
{ "INT3435", (unsigned long)&lpt_uart_dev_desc },
199200
{ "INT3436", (unsigned long)&lpt_sdio_dev_desc },
@@ -221,9 +222,11 @@ static int register_device_clock(struct acpi_device *adev,
221222
{
222223
const struct lpss_device_desc *dev_desc = pdata->dev_desc;
223224
struct lpss_shared_clock *shared_clock = dev_desc->shared_clock;
225+
const char *devname = dev_name(&adev->dev);
224226
struct clk *clk = ERR_PTR(-ENODEV);
225227
struct lpss_clk_data *clk_data;
226-
const char *parent;
228+
const char *parent, *clk_name;
229+
void __iomem *prv_base;
227230

228231
if (!lpss_clk_dev)
229232
lpt_register_clock_device();
@@ -234,7 +237,7 @@ static int register_device_clock(struct acpi_device *adev,
234237

235238
if (dev_desc->clkdev_name) {
236239
clk_register_clkdev(clk_data->clk, dev_desc->clkdev_name,
237-
dev_name(&adev->dev));
240+
devname);
238241
return 0;
239242
}
240243

@@ -243,6 +246,7 @@ static int register_device_clock(struct acpi_device *adev,
243246
return -ENODATA;
244247

245248
parent = clk_data->name;
249+
prv_base = pdata->mmio_base + dev_desc->prv_offset;
246250

247251
if (shared_clock) {
248252
clk = shared_clock->clk;
@@ -256,16 +260,41 @@ static int register_device_clock(struct acpi_device *adev,
256260
}
257261

258262
if (dev_desc->clk_gate) {
259-
clk = clk_register_gate(NULL, dev_name(&adev->dev), parent, 0,
260-
pdata->mmio_base + dev_desc->prv_offset,
261-
0, 0, NULL);
262-
pdata->clk = clk;
263+
clk = clk_register_gate(NULL, devname, parent, 0,
264+
prv_base, 0, 0, NULL);
265+
parent = devname;
266+
}
267+
268+
if (dev_desc->clk_divider) {
269+
/* Prevent division by zero */
270+
if (!readl(prv_base))
271+
writel(LPSS_CLK_DIVIDER_DEF_MASK, prv_base);
272+
273+
clk_name = kasprintf(GFP_KERNEL, "%s-div", devname);
274+
if (!clk_name)
275+
return -ENOMEM;
276+
clk = clk_register_fractional_divider(NULL, clk_name, parent,
277+
0, prv_base,
278+
1, 15, 16, 15, 0, NULL);
279+
parent = clk_name;
280+
281+
clk_name = kasprintf(GFP_KERNEL, "%s-update", devname);
282+
if (!clk_name) {
283+
kfree(parent);
284+
return -ENOMEM;
285+
}
286+
clk = clk_register_gate(NULL, clk_name, parent,
287+
CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE,
288+
prv_base, 31, 0, NULL);
289+
kfree(parent);
290+
kfree(clk_name);
263291
}
264292

265293
if (IS_ERR(clk))
266294
return PTR_ERR(clk);
267295

268-
clk_register_clkdev(clk, NULL, dev_name(&adev->dev));
296+
pdata->clk = clk;
297+
clk_register_clkdev(clk, NULL, devname);
269298
return 0;
270299
}
271300

0 commit comments

Comments
 (0)