Merge branches 'clk-st', 'clk-si' and 'clk-hisilicon' into clk-next
- Stop using clock-output-names in ST clk drivers * clk-st: dt-bindings: clock: st: clkgen-fsyn: add new introduced compatible clk: st: clkgen-fsyn: embed soc clock outputs within compatible data dt-bindings: clock: st: clkgen-pll: add new introduced compatible clk: st: clkgen-pll: embed soc clock outputs within compatible data dt-bindings: clock: st: flexgen: add new introduced compatible clk: st: flexgen: embed soc clock outputs within compatible data clk: st: clkgen-pll: remove unused variable of struct clkgen_pll * clk-si: clk: si5341: Add sysfs properties to allow checking/resetting device faults clk: si5341: Add silabs,iovdd-33 property clk: si5341: Add silabs,xaxb-ext-clk property clk: si5341: Allow different output VDD_SEL values clk: si5341: Update initialization magic clk: si5341: Check for input clock presence and PLL lock on startup clk: si5341: Avoid divide errors due to bogus register contents clk: si5341: Wait for DEVICE_READY on startup dt-bindings: clock: clk-si5341: Add new attributes * clk-hisilicon: clk: hisilicon: Add clock driver for hi3559A SoC dt-bindings: Document the hi3559a clock bindings
This commit is contained in:
commit
d2b21013bf
|
@ -0,0 +1,59 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/clock/hisilicon,hi3559av100-clock.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Hisilicon SOC Clock for HI3559AV100
|
||||
|
||||
maintainers:
|
||||
- Dongjiu Geng <gengdongjiu@huawei.com>
|
||||
|
||||
description: |
|
||||
Hisilicon SOC clock control module which supports the clocks, resets and
|
||||
power domains on HI3559AV100.
|
||||
|
||||
See also:
|
||||
dt-bindings/clock/hi3559av100-clock.h
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- hisilicon,hi3559av100-clock
|
||||
- hisilicon,hi3559av100-shub-clock
|
||||
|
||||
reg:
|
||||
minItems: 1
|
||||
maxItems: 2
|
||||
|
||||
'#clock-cells':
|
||||
const: 1
|
||||
|
||||
'#reset-cells':
|
||||
const: 2
|
||||
description: |
|
||||
First cell is reset request register offset.
|
||||
Second cell is bit offset in reset request register.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- '#clock-cells'
|
||||
- '#reset-cells'
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
soc {
|
||||
#address-cells = <2>;
|
||||
#size-cells = <2>;
|
||||
|
||||
clock-controller@12010000 {
|
||||
compatible = "hisilicon,hi3559av100-clock";
|
||||
#clock-cells = <1>;
|
||||
#reset-cells = <2>;
|
||||
reg = <0x0 0x12010000 0x0 0x10000>;
|
||||
};
|
||||
};
|
||||
...
|
|
@ -24,9 +24,8 @@ it.
|
|||
|
||||
The device type, speed grade and revision are determined runtime by probing.
|
||||
|
||||
The driver currently only supports XTAL input mode, and does not support any
|
||||
fancy input configurations. They can still be programmed into the chip and
|
||||
the driver will leave them "as is".
|
||||
The driver currently does not support any fancy input configurations. They can
|
||||
still be programmed into the chip and the driver will leave them "as is".
|
||||
|
||||
==I2C device node==
|
||||
|
||||
|
@ -45,9 +44,9 @@ Required properties:
|
|||
corresponding to inputs. Use a fixed clock for the "xtal" input.
|
||||
At least one must be present.
|
||||
- clock-names: One of: "xtal", "in0", "in1", "in2"
|
||||
- vdd-supply: Regulator node for VDD
|
||||
|
||||
Optional properties:
|
||||
- vdd-supply: Regulator node for VDD
|
||||
- vdda-supply: Regulator node for VDDA
|
||||
- vdds-supply: Regulator node for VDDS
|
||||
- silabs,pll-m-num, silabs,pll-m-den: Numerator and denominator for PLL
|
||||
|
@ -60,7 +59,14 @@ Optional properties:
|
|||
be initialized, and always performs the soft-reset routine. Since this will
|
||||
temporarily stop all output clocks, don't do this if the chip is generating
|
||||
the CPU clock for example.
|
||||
- silabs,xaxb-ext-clk: When present, indicates that the XA/XB pins are used
|
||||
in EXTCLK (external reference clock) rather than XTAL (crystal) mode.
|
||||
- interrupts: Interrupt for INTRb pin.
|
||||
- silabs,iovdd-33: When present, indicates that the I2C lines are using 3.3V
|
||||
rather than 1.8V thresholds.
|
||||
- vddoX-supply (where X is an output index): Regulator node for VDDO for the
|
||||
specified output. The driver selects the output VDD_SEL setting based on this
|
||||
voltage.
|
||||
- #address-cells: shall be set to 1.
|
||||
- #size-cells: shall be set to 0.
|
||||
|
||||
|
@ -77,8 +83,6 @@ Required child node properties:
|
|||
- reg: number of clock output.
|
||||
|
||||
Optional child node properties:
|
||||
- vdd-supply: Regulator node for VDD for this output. The driver selects default
|
||||
values for common-mode and amplitude based on the voltage.
|
||||
- silabs,format: Output format, one of:
|
||||
1 = differential (defaults to LVDS levels)
|
||||
2 = low-power (defaults to HCSL levels)
|
||||
|
|
|
@ -10,7 +10,10 @@ Required properties:
|
|||
|
||||
- compatible : shall be:
|
||||
"st,clkgen-pll0"
|
||||
"st,clkgen-pll0-a0"
|
||||
"st,clkgen-pll0-c0"
|
||||
"st,clkgen-pll1"
|
||||
"st,clkgen-pll1-c0"
|
||||
"st,stih407-clkgen-plla9"
|
||||
"st,stih418-clkgen-plla9"
|
||||
|
||||
|
|
|
@ -64,6 +64,16 @@ Required properties:
|
|||
audio use case)
|
||||
"st,flexgen-video", "st,flexgen" (enable clock propagation on parent
|
||||
and activate synchronous mode)
|
||||
"st,flexgen-stih407-a0"
|
||||
"st,flexgen-stih410-a0"
|
||||
"st,flexgen-stih407-c0"
|
||||
"st,flexgen-stih410-c0"
|
||||
"st,flexgen-stih418-c0"
|
||||
"st,flexgen-stih407-d0"
|
||||
"st,flexgen-stih410-d0"
|
||||
"st,flexgen-stih407-d2"
|
||||
"st,flexgen-stih418-d2"
|
||||
"st,flexgen-stih407-d3"
|
||||
|
||||
- #clock-cells : from common clock binding; shall be set to 1 (multiple clock
|
||||
outputs).
|
||||
|
|
|
@ -12,6 +12,9 @@ This binding uses the common clock binding[1].
|
|||
Required properties:
|
||||
- compatible : shall be:
|
||||
"st,quadfs"
|
||||
"st,quadfs-d0"
|
||||
"st,quadfs-d2"
|
||||
"st,quadfs-d3"
|
||||
"st,quadfs-pll"
|
||||
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include <linux/i2c.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/slab.h>
|
||||
#include <asm/unaligned.h>
|
||||
|
||||
|
@ -59,6 +60,7 @@ struct clk_si5341_synth {
|
|||
struct clk_si5341_output {
|
||||
struct clk_hw hw;
|
||||
struct clk_si5341 *data;
|
||||
struct regulator *vddo_reg;
|
||||
u8 index;
|
||||
};
|
||||
#define to_clk_si5341_output(_hw) \
|
||||
|
@ -78,12 +80,15 @@ struct clk_si5341 {
|
|||
u8 num_outputs;
|
||||
u8 num_synth;
|
||||
u16 chip_id;
|
||||
bool xaxb_ext_clk;
|
||||
bool iovdd_33;
|
||||
};
|
||||
#define to_clk_si5341(_hw) container_of(_hw, struct clk_si5341, hw)
|
||||
|
||||
struct clk_si5341_output_config {
|
||||
u8 out_format_drv_bits;
|
||||
u8 out_cm_ampl_bits;
|
||||
u8 vdd_sel_bits;
|
||||
bool synth_master;
|
||||
bool always_on;
|
||||
};
|
||||
|
@ -92,12 +97,23 @@ struct clk_si5341_output_config {
|
|||
#define SI5341_PN_BASE 0x0002
|
||||
#define SI5341_DEVICE_REV 0x0005
|
||||
#define SI5341_STATUS 0x000C
|
||||
#define SI5341_LOS 0x000D
|
||||
#define SI5341_STATUS_STICKY 0x0011
|
||||
#define SI5341_LOS_STICKY 0x0012
|
||||
#define SI5341_SOFT_RST 0x001C
|
||||
#define SI5341_IN_SEL 0x0021
|
||||
#define SI5341_DEVICE_READY 0x00FE
|
||||
#define SI5341_XAXB_CFG 0x090E
|
||||
#define SI5341_IO_VDD_SEL 0x0943
|
||||
#define SI5341_IN_EN 0x0949
|
||||
#define SI5341_INX_TO_PFD_EN 0x094A
|
||||
|
||||
/* Status bits */
|
||||
#define SI5341_STATUS_SYSINCAL BIT(0)
|
||||
#define SI5341_STATUS_LOSXAXB BIT(1)
|
||||
#define SI5341_STATUS_LOSREF BIT(2)
|
||||
#define SI5341_STATUS_LOL BIT(3)
|
||||
|
||||
/* Input selection */
|
||||
#define SI5341_IN_SEL_MASK 0x06
|
||||
#define SI5341_IN_SEL_SHIFT 1
|
||||
|
@ -126,6 +142,8 @@ struct clk_si5341_output_config {
|
|||
#define SI5341_OUT_R_REG(output) \
|
||||
((output)->data->reg_rdiv_offset[(output)->index])
|
||||
|
||||
#define SI5341_OUT_MUX_VDD_SEL_MASK 0x38
|
||||
|
||||
/* Synthesize N divider */
|
||||
#define SI5341_SYNTH_N_NUM(x) (0x0302 + ((x) * 11))
|
||||
#define SI5341_SYNTH_N_DEN(x) (0x0308 + ((x) * 11))
|
||||
|
@ -335,11 +353,12 @@ static const struct si5341_reg_default si5341_reg_defaults[] = {
|
|||
{ 0x0804, 0x00 }, /* Not in datasheet */
|
||||
{ 0x090E, 0x02 }, /* XAXB_EXTCLK_EN=0 XAXB_PDNB=1 (use XTAL) */
|
||||
{ 0x091C, 0x04 }, /* ZDM_EN=4 (Normal mode) */
|
||||
{ 0x0943, 0x00 }, /* IO_VDD_SEL=0 (0=1v8, use 1=3v3) */
|
||||
{ 0x0949, 0x00 }, /* IN_EN (disable input clocks) */
|
||||
{ 0x094A, 0x00 }, /* INx_TO_PFD_EN (disabled) */
|
||||
{ 0x0A02, 0x00 }, /* Not in datasheet */
|
||||
{ 0x0B44, 0x0F }, /* PDIV_ENB (datasheet does not mention what it is) */
|
||||
{ 0x0B57, 0x10 }, /* VCO_RESET_CALCODE (not described in datasheet) */
|
||||
{ 0x0B58, 0x05 }, /* VCO_RESET_CALCODE (not described in datasheet) */
|
||||
};
|
||||
|
||||
/* Read and interpret a 44-bit followed by a 32-bit value in the regmap */
|
||||
|
@ -512,9 +531,11 @@ static int si5341_clk_reparent(struct clk_si5341 *data, u8 index)
|
|||
if (err < 0)
|
||||
return err;
|
||||
|
||||
/* Power up XTAL oscillator and buffer */
|
||||
/* Power up XTAL oscillator and buffer, select clock mode */
|
||||
err = regmap_update_bits(data->regmap, SI5341_XAXB_CFG,
|
||||
SI5341_XAXB_CFG_PDNB, SI5341_XAXB_CFG_PDNB);
|
||||
SI5341_XAXB_CFG_PDNB | SI5341_XAXB_CFG_EXTCLK_EN,
|
||||
SI5341_XAXB_CFG_PDNB | (data->xaxb_ext_clk ?
|
||||
SI5341_XAXB_CFG_EXTCLK_EN : 0));
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
|
@ -623,6 +644,9 @@ static unsigned long si5341_synth_clk_recalc_rate(struct clk_hw *hw,
|
|||
SI5341_SYNTH_N_NUM(synth->index), &n_num, &n_den);
|
||||
if (err < 0)
|
||||
return err;
|
||||
/* Check for bogus/uninitialized settings */
|
||||
if (!n_num || !n_den)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* n_num and n_den are shifted left as much as possible, so to prevent
|
||||
|
@ -806,6 +830,9 @@ static long si5341_output_clk_round_rate(struct clk_hw *hw, unsigned long rate,
|
|||
{
|
||||
unsigned long r;
|
||||
|
||||
if (!rate)
|
||||
return 0;
|
||||
|
||||
r = *parent_rate >> 1;
|
||||
|
||||
/* If rate is an even divisor, no changes to parent required */
|
||||
|
@ -834,11 +861,16 @@ static int si5341_output_clk_set_rate(struct clk_hw *hw, unsigned long rate,
|
|||
unsigned long parent_rate)
|
||||
{
|
||||
struct clk_si5341_output *output = to_clk_si5341_output(hw);
|
||||
/* Frequency divider is (r_div + 1) * 2 */
|
||||
u32 r_div = (parent_rate / rate) >> 1;
|
||||
u32 r_div;
|
||||
int err;
|
||||
u8 r[3];
|
||||
|
||||
if (!rate)
|
||||
return -EINVAL;
|
||||
|
||||
/* Frequency divider is (r_div + 1) * 2 */
|
||||
r_div = (parent_rate / rate) >> 1;
|
||||
|
||||
if (r_div <= 1)
|
||||
r_div = 0;
|
||||
else if (r_div >= BIT(24))
|
||||
|
@ -1083,7 +1115,7 @@ static const struct si5341_reg_default si5341_preamble[] = {
|
|||
{ 0x0B25, 0x00 },
|
||||
{ 0x0502, 0x01 },
|
||||
{ 0x0505, 0x03 },
|
||||
{ 0x0957, 0x1F },
|
||||
{ 0x0957, 0x17 },
|
||||
{ 0x0B4E, 0x1A },
|
||||
};
|
||||
|
||||
|
@ -1129,6 +1161,11 @@ static int si5341_finalize_defaults(struct clk_si5341 *data)
|
|||
int res;
|
||||
u32 revision;
|
||||
|
||||
res = regmap_write(data->regmap, SI5341_IO_VDD_SEL,
|
||||
data->iovdd_33 ? 1 : 0);
|
||||
if (res < 0)
|
||||
return res;
|
||||
|
||||
res = regmap_read(data->regmap, SI5341_DEVICE_REV, &revision);
|
||||
if (res < 0)
|
||||
return res;
|
||||
|
@ -1189,6 +1226,32 @@ static const struct regmap_range_cfg si5341_regmap_ranges[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static int si5341_wait_device_ready(struct i2c_client *client)
|
||||
{
|
||||
int count;
|
||||
|
||||
/* Datasheet warns: Any attempt to read or write any register other
|
||||
* than DEVICE_READY before DEVICE_READY reads as 0x0F may corrupt the
|
||||
* NVM programming and may corrupt the register contents, as they are
|
||||
* read from NVM. Note that this includes accesses to the PAGE register.
|
||||
* Also: DEVICE_READY is available on every register page, so no page
|
||||
* change is needed to read it.
|
||||
* Do this outside regmap to avoid automatic PAGE register access.
|
||||
* May take up to 300ms to complete.
|
||||
*/
|
||||
for (count = 0; count < 15; ++count) {
|
||||
s32 result = i2c_smbus_read_byte_data(client,
|
||||
SI5341_DEVICE_READY);
|
||||
if (result < 0)
|
||||
return result;
|
||||
if (result == 0x0F)
|
||||
return 0;
|
||||
msleep(20);
|
||||
}
|
||||
dev_err(&client->dev, "timeout waiting for DEVICE_READY\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
static const struct regmap_config si5341_regmap_config = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
|
@ -1199,11 +1262,11 @@ static const struct regmap_config si5341_regmap_config = {
|
|||
.volatile_table = &si5341_regmap_volatile,
|
||||
};
|
||||
|
||||
static int si5341_dt_parse_dt(struct i2c_client *client,
|
||||
struct clk_si5341_output_config *config)
|
||||
static int si5341_dt_parse_dt(struct clk_si5341 *data,
|
||||
struct clk_si5341_output_config *config)
|
||||
{
|
||||
struct device_node *child;
|
||||
struct device_node *np = client->dev.of_node;
|
||||
struct device_node *np = data->i2c_client->dev.of_node;
|
||||
u32 num;
|
||||
u32 val;
|
||||
|
||||
|
@ -1212,13 +1275,13 @@ static int si5341_dt_parse_dt(struct i2c_client *client,
|
|||
|
||||
for_each_child_of_node(np, child) {
|
||||
if (of_property_read_u32(child, "reg", &num)) {
|
||||
dev_err(&client->dev, "missing reg property of %s\n",
|
||||
dev_err(&data->i2c_client->dev, "missing reg property of %s\n",
|
||||
child->name);
|
||||
goto put_child;
|
||||
}
|
||||
|
||||
if (num >= SI5341_MAX_NUM_OUTPUTS) {
|
||||
dev_err(&client->dev, "invalid clkout %d\n", num);
|
||||
dev_err(&data->i2c_client->dev, "invalid clkout %d\n", num);
|
||||
goto put_child;
|
||||
}
|
||||
|
||||
|
@ -1237,7 +1300,7 @@ static int si5341_dt_parse_dt(struct i2c_client *client,
|
|||
config[num].out_format_drv_bits |= 0xc0;
|
||||
break;
|
||||
default:
|
||||
dev_err(&client->dev,
|
||||
dev_err(&data->i2c_client->dev,
|
||||
"invalid silabs,format %u for %u\n",
|
||||
val, num);
|
||||
goto put_child;
|
||||
|
@ -1250,7 +1313,7 @@ static int si5341_dt_parse_dt(struct i2c_client *client,
|
|||
|
||||
if (!of_property_read_u32(child, "silabs,common-mode", &val)) {
|
||||
if (val > 0xf) {
|
||||
dev_err(&client->dev,
|
||||
dev_err(&data->i2c_client->dev,
|
||||
"invalid silabs,common-mode %u\n",
|
||||
val);
|
||||
goto put_child;
|
||||
|
@ -1261,7 +1324,7 @@ static int si5341_dt_parse_dt(struct i2c_client *client,
|
|||
|
||||
if (!of_property_read_u32(child, "silabs,amplitude", &val)) {
|
||||
if (val > 0xf) {
|
||||
dev_err(&client->dev,
|
||||
dev_err(&data->i2c_client->dev,
|
||||
"invalid silabs,amplitude %u\n",
|
||||
val);
|
||||
goto put_child;
|
||||
|
@ -1278,6 +1341,34 @@ static int si5341_dt_parse_dt(struct i2c_client *client,
|
|||
|
||||
config[num].always_on =
|
||||
of_property_read_bool(child, "always-on");
|
||||
|
||||
config[num].vdd_sel_bits = 0x08;
|
||||
if (data->clk[num].vddo_reg) {
|
||||
int vdd = regulator_get_voltage(data->clk[num].vddo_reg);
|
||||
|
||||
switch (vdd) {
|
||||
case 3300000:
|
||||
config[num].vdd_sel_bits |= 0 << 4;
|
||||
break;
|
||||
case 1800000:
|
||||
config[num].vdd_sel_bits |= 1 << 4;
|
||||
break;
|
||||
case 2500000:
|
||||
config[num].vdd_sel_bits |= 2 << 4;
|
||||
break;
|
||||
default:
|
||||
dev_err(&data->i2c_client->dev,
|
||||
"unsupported vddo voltage %d for %s\n",
|
||||
vdd, child->name);
|
||||
goto put_child;
|
||||
}
|
||||
} else {
|
||||
/* chip seems to default to 2.5V when not set */
|
||||
dev_warn(&data->i2c_client->dev,
|
||||
"no regulator set, defaulting vdd_sel to 2.5V for %s\n",
|
||||
child->name);
|
||||
config[num].vdd_sel_bits |= 2 << 4;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -1366,6 +1457,94 @@ static int si5341_clk_select_active_input(struct clk_si5341 *data)
|
|||
return res;
|
||||
}
|
||||
|
||||
static ssize_t input_present_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct clk_si5341 *data = dev_get_drvdata(dev);
|
||||
u32 status;
|
||||
int res = regmap_read(data->regmap, SI5341_STATUS, &status);
|
||||
|
||||
if (res < 0)
|
||||
return res;
|
||||
res = !(status & SI5341_STATUS_LOSREF);
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", res);
|
||||
}
|
||||
static DEVICE_ATTR_RO(input_present);
|
||||
|
||||
static ssize_t input_present_sticky_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct clk_si5341 *data = dev_get_drvdata(dev);
|
||||
u32 status;
|
||||
int res = regmap_read(data->regmap, SI5341_STATUS_STICKY, &status);
|
||||
|
||||
if (res < 0)
|
||||
return res;
|
||||
res = !(status & SI5341_STATUS_LOSREF);
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", res);
|
||||
}
|
||||
static DEVICE_ATTR_RO(input_present_sticky);
|
||||
|
||||
static ssize_t pll_locked_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct clk_si5341 *data = dev_get_drvdata(dev);
|
||||
u32 status;
|
||||
int res = regmap_read(data->regmap, SI5341_STATUS, &status);
|
||||
|
||||
if (res < 0)
|
||||
return res;
|
||||
res = !(status & SI5341_STATUS_LOL);
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", res);
|
||||
}
|
||||
static DEVICE_ATTR_RO(pll_locked);
|
||||
|
||||
static ssize_t pll_locked_sticky_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct clk_si5341 *data = dev_get_drvdata(dev);
|
||||
u32 status;
|
||||
int res = regmap_read(data->regmap, SI5341_STATUS_STICKY, &status);
|
||||
|
||||
if (res < 0)
|
||||
return res;
|
||||
res = !(status & SI5341_STATUS_LOL);
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", res);
|
||||
}
|
||||
static DEVICE_ATTR_RO(pll_locked_sticky);
|
||||
|
||||
static ssize_t clear_sticky_store(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct clk_si5341 *data = dev_get_drvdata(dev);
|
||||
long val;
|
||||
|
||||
if (kstrtol(buf, 10, &val))
|
||||
return -EINVAL;
|
||||
if (val) {
|
||||
int res = regmap_write(data->regmap, SI5341_STATUS_STICKY, 0);
|
||||
|
||||
if (res < 0)
|
||||
return res;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
static DEVICE_ATTR_WO(clear_sticky);
|
||||
|
||||
static const struct attribute *si5341_attributes[] = {
|
||||
&dev_attr_input_present.attr,
|
||||
&dev_attr_input_present_sticky.attr,
|
||||
&dev_attr_pll_locked.attr,
|
||||
&dev_attr_pll_locked_sticky.attr,
|
||||
&dev_attr_clear_sticky.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
static int si5341_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
|
@ -1378,6 +1557,7 @@ static int si5341_probe(struct i2c_client *client,
|
|||
unsigned int i;
|
||||
struct clk_si5341_output_config config[SI5341_MAX_NUM_OUTPUTS];
|
||||
bool initialization_required;
|
||||
u32 status;
|
||||
|
||||
data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
|
||||
if (!data)
|
||||
|
@ -1385,6 +1565,11 @@ static int si5341_probe(struct i2c_client *client,
|
|||
|
||||
data->i2c_client = client;
|
||||
|
||||
/* Must be done before otherwise touching hardware */
|
||||
err = si5341_wait_device_ready(client);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
for (i = 0; i < SI5341_NUM_INPUTS; ++i) {
|
||||
input = devm_clk_get(&client->dev, si5341_input_clock_names[i]);
|
||||
if (IS_ERR(input)) {
|
||||
|
@ -1397,9 +1582,33 @@ static int si5341_probe(struct i2c_client *client,
|
|||
}
|
||||
}
|
||||
|
||||
err = si5341_dt_parse_dt(client, config);
|
||||
for (i = 0; i < SI5341_MAX_NUM_OUTPUTS; ++i) {
|
||||
char reg_name[10];
|
||||
|
||||
snprintf(reg_name, sizeof(reg_name), "vddo%d", i);
|
||||
data->clk[i].vddo_reg = devm_regulator_get_optional(
|
||||
&client->dev, reg_name);
|
||||
if (IS_ERR(data->clk[i].vddo_reg)) {
|
||||
err = PTR_ERR(data->clk[i].vddo_reg);
|
||||
data->clk[i].vddo_reg = NULL;
|
||||
if (err == -ENODEV)
|
||||
continue;
|
||||
goto cleanup;
|
||||
} else {
|
||||
err = regulator_enable(data->clk[i].vddo_reg);
|
||||
if (err) {
|
||||
dev_err(&client->dev,
|
||||
"failed to enable %s regulator: %d\n",
|
||||
reg_name, err);
|
||||
data->clk[i].vddo_reg = NULL;
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
err = si5341_dt_parse_dt(data, config);
|
||||
if (err)
|
||||
return err;
|
||||
goto cleanup;
|
||||
|
||||
if (of_property_read_string(client->dev.of_node, "clock-output-names",
|
||||
&init.name))
|
||||
|
@ -1407,34 +1616,40 @@ static int si5341_probe(struct i2c_client *client,
|
|||
root_clock_name = init.name;
|
||||
|
||||
data->regmap = devm_regmap_init_i2c(client, &si5341_regmap_config);
|
||||
if (IS_ERR(data->regmap))
|
||||
return PTR_ERR(data->regmap);
|
||||
if (IS_ERR(data->regmap)) {
|
||||
err = PTR_ERR(data->regmap);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
i2c_set_clientdata(client, data);
|
||||
|
||||
err = si5341_probe_chip_id(data);
|
||||
if (err < 0)
|
||||
return err;
|
||||
goto cleanup;
|
||||
|
||||
if (of_property_read_bool(client->dev.of_node, "silabs,reprogram")) {
|
||||
initialization_required = true;
|
||||
} else {
|
||||
err = si5341_is_programmed_already(data);
|
||||
if (err < 0)
|
||||
return err;
|
||||
goto cleanup;
|
||||
|
||||
initialization_required = !err;
|
||||
}
|
||||
data->xaxb_ext_clk = of_property_read_bool(client->dev.of_node,
|
||||
"silabs,xaxb-ext-clk");
|
||||
data->iovdd_33 = of_property_read_bool(client->dev.of_node,
|
||||
"silabs,iovdd-33");
|
||||
|
||||
if (initialization_required) {
|
||||
/* Populate the regmap cache in preparation for "cache only" */
|
||||
err = si5341_read_settings(data);
|
||||
if (err < 0)
|
||||
return err;
|
||||
goto cleanup;
|
||||
|
||||
err = si5341_send_preamble(data);
|
||||
if (err < 0)
|
||||
return err;
|
||||
goto cleanup;
|
||||
|
||||
/*
|
||||
* We intend to send all 'final' register values in a single
|
||||
|
@ -1447,19 +1662,19 @@ static int si5341_probe(struct i2c_client *client,
|
|||
err = si5341_write_multiple(data, si5341_reg_defaults,
|
||||
ARRAY_SIZE(si5341_reg_defaults));
|
||||
if (err < 0)
|
||||
return err;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Input must be up and running at this point */
|
||||
err = si5341_clk_select_active_input(data);
|
||||
if (err < 0)
|
||||
return err;
|
||||
goto cleanup;
|
||||
|
||||
if (initialization_required) {
|
||||
/* PLL configuration is required */
|
||||
err = si5341_initialize_pll(data);
|
||||
if (err < 0)
|
||||
return err;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Register the PLL */
|
||||
|
@ -1472,7 +1687,7 @@ static int si5341_probe(struct i2c_client *client,
|
|||
err = devm_clk_hw_register(&client->dev, &data->hw);
|
||||
if (err) {
|
||||
dev_err(&client->dev, "clock registration failed\n");
|
||||
return err;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
init.num_parents = 1;
|
||||
|
@ -1509,13 +1724,17 @@ static int si5341_probe(struct i2c_client *client,
|
|||
regmap_write(data->regmap,
|
||||
SI5341_OUT_CM(&data->clk[i]),
|
||||
config[i].out_cm_ampl_bits);
|
||||
regmap_update_bits(data->regmap,
|
||||
SI5341_OUT_MUX_SEL(&data->clk[i]),
|
||||
SI5341_OUT_MUX_VDD_SEL_MASK,
|
||||
config[i].vdd_sel_bits);
|
||||
}
|
||||
err = devm_clk_hw_register(&client->dev, &data->clk[i].hw);
|
||||
kfree(init.name); /* clock framework made a copy of the name */
|
||||
if (err) {
|
||||
dev_err(&client->dev,
|
||||
"output %u registration failed\n", i);
|
||||
return err;
|
||||
goto cleanup;
|
||||
}
|
||||
if (config[i].always_on)
|
||||
clk_prepare(data->clk[i].hw.clk);
|
||||
|
@ -1525,7 +1744,7 @@ static int si5341_probe(struct i2c_client *client,
|
|||
data);
|
||||
if (err) {
|
||||
dev_err(&client->dev, "unable to add clk provider\n");
|
||||
return err;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (initialization_required) {
|
||||
|
@ -1533,11 +1752,33 @@ static int si5341_probe(struct i2c_client *client,
|
|||
regcache_cache_only(data->regmap, false);
|
||||
err = regcache_sync(data->regmap);
|
||||
if (err < 0)
|
||||
return err;
|
||||
goto cleanup;
|
||||
|
||||
err = si5341_finalize_defaults(data);
|
||||
if (err < 0)
|
||||
return err;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* wait for device to report input clock present and PLL lock */
|
||||
err = regmap_read_poll_timeout(data->regmap, SI5341_STATUS, status,
|
||||
!(status & (SI5341_STATUS_LOSREF | SI5341_STATUS_LOL)),
|
||||
10000, 250000);
|
||||
if (err) {
|
||||
dev_err(&client->dev, "Error waiting for input clock or PLL lock\n");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* clear sticky alarm bits from initialization */
|
||||
err = regmap_write(data->regmap, SI5341_STATUS_STICKY, 0);
|
||||
if (err) {
|
||||
dev_err(&client->dev, "unable to clear sticky status\n");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
err = sysfs_create_files(&client->dev.kobj, si5341_attributes);
|
||||
if (err) {
|
||||
dev_err(&client->dev, "unable to create sysfs files\n");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Free the names, clk framework makes copies */
|
||||
|
@ -1545,6 +1786,28 @@ static int si5341_probe(struct i2c_client *client,
|
|||
devm_kfree(&client->dev, (void *)synth_clock_names[i]);
|
||||
|
||||
return 0;
|
||||
|
||||
cleanup:
|
||||
for (i = 0; i < SI5341_MAX_NUM_OUTPUTS; ++i) {
|
||||
if (data->clk[i].vddo_reg)
|
||||
regulator_disable(data->clk[i].vddo_reg);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
static int si5341_remove(struct i2c_client *client)
|
||||
{
|
||||
struct clk_si5341 *data = i2c_get_clientdata(client);
|
||||
int i;
|
||||
|
||||
sysfs_remove_files(&client->dev.kobj, si5341_attributes);
|
||||
|
||||
for (i = 0; i < SI5341_MAX_NUM_OUTPUTS; ++i) {
|
||||
if (data->clk[i].vddo_reg)
|
||||
regulator_disable(data->clk[i].vddo_reg);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct i2c_device_id si5341_id[] = {
|
||||
|
@ -1573,6 +1836,7 @@ static struct i2c_driver si5341_driver = {
|
|||
.of_match_table = clk_si5341_of_match,
|
||||
},
|
||||
.probe = si5341_probe,
|
||||
.remove = si5341_remove,
|
||||
.id_table = si5341_id,
|
||||
};
|
||||
module_i2c_driver(si5341_driver);
|
||||
|
|
|
@ -15,6 +15,13 @@ config COMMON_CLK_HI3519
|
|||
help
|
||||
Build the clock driver for hi3519.
|
||||
|
||||
config COMMON_CLK_HI3559A
|
||||
bool "Hi3559A Clock Driver"
|
||||
depends on ARCH_HISI || COMPILE_TEST
|
||||
default ARCH_HISI
|
||||
help
|
||||
Build the clock driver for hi3559a.
|
||||
|
||||
config COMMON_CLK_HI3660
|
||||
bool "Hi3660 Clock Driver"
|
||||
depends on ARCH_HISI || COMPILE_TEST
|
||||
|
|
|
@ -10,6 +10,7 @@ obj-$(CONFIG_ARCH_HIP04) += clk-hip04.o
|
|||
obj-$(CONFIG_ARCH_HIX5HD2) += clk-hix5hd2.o
|
||||
obj-$(CONFIG_COMMON_CLK_HI3516CV300) += crg-hi3516cv300.o
|
||||
obj-$(CONFIG_COMMON_CLK_HI3519) += clk-hi3519.o
|
||||
obj-$(CONFIG_COMMON_CLK_HI3559A) += clk-hi3559a.o
|
||||
obj-$(CONFIG_COMMON_CLK_HI3660) += clk-hi3660.o
|
||||
obj-$(CONFIG_COMMON_CLK_HI3670) += clk-hi3670.o
|
||||
obj-$(CONFIG_COMMON_CLK_HI3798CV200) += crg-hi3798cv200.o
|
||||
|
|
|
@ -0,0 +1,846 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Hisilicon Hi3559A clock driver
|
||||
*
|
||||
* Copyright (c) 2019-2020, Huawei Tech. Co., Ltd.
|
||||
*
|
||||
* Author: Dongjiu Geng <gengdongjiu@huawei.com>
|
||||
*/
|
||||
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <dt-bindings/clock/hi3559av100-clock.h>
|
||||
|
||||
#include "clk.h"
|
||||
#include "crg.h"
|
||||
#include "reset.h"
|
||||
|
||||
#define CRG_BASE_ADDR 0x18020000
|
||||
#define PLL_MASK_WIDTH 24
|
||||
|
||||
struct hi3559av100_pll_clock {
|
||||
u32 id;
|
||||
const char *name;
|
||||
const char *parent_name;
|
||||
const u32 ctrl_reg1;
|
||||
const u8 frac_shift;
|
||||
const u8 frac_width;
|
||||
const u8 postdiv1_shift;
|
||||
const u8 postdiv1_width;
|
||||
const u8 postdiv2_shift;
|
||||
const u8 postdiv2_width;
|
||||
const u32 ctrl_reg2;
|
||||
const u8 fbdiv_shift;
|
||||
const u8 fbdiv_width;
|
||||
const u8 refdiv_shift;
|
||||
const u8 refdiv_width;
|
||||
};
|
||||
|
||||
struct hi3559av100_clk_pll {
|
||||
struct clk_hw hw;
|
||||
u32 id;
|
||||
void __iomem *ctrl_reg1;
|
||||
u8 frac_shift;
|
||||
u8 frac_width;
|
||||
u8 postdiv1_shift;
|
||||
u8 postdiv1_width;
|
||||
u8 postdiv2_shift;
|
||||
u8 postdiv2_width;
|
||||
void __iomem *ctrl_reg2;
|
||||
u8 fbdiv_shift;
|
||||
u8 fbdiv_width;
|
||||
u8 refdiv_shift;
|
||||
u8 refdiv_width;
|
||||
};
|
||||
|
||||
/* soc clk config */
|
||||
static const struct hisi_fixed_rate_clock hi3559av100_fixed_rate_clks_crg[] = {
|
||||
{ HI3559AV100_FIXED_1188M, "1188m", NULL, 0, 1188000000, },
|
||||
{ HI3559AV100_FIXED_1000M, "1000m", NULL, 0, 1000000000, },
|
||||
{ HI3559AV100_FIXED_842M, "842m", NULL, 0, 842000000, },
|
||||
{ HI3559AV100_FIXED_792M, "792m", NULL, 0, 792000000, },
|
||||
{ HI3559AV100_FIXED_750M, "750m", NULL, 0, 750000000, },
|
||||
{ HI3559AV100_FIXED_710M, "710m", NULL, 0, 710000000, },
|
||||
{ HI3559AV100_FIXED_680M, "680m", NULL, 0, 680000000, },
|
||||
{ HI3559AV100_FIXED_667M, "667m", NULL, 0, 667000000, },
|
||||
{ HI3559AV100_FIXED_631M, "631m", NULL, 0, 631000000, },
|
||||
{ HI3559AV100_FIXED_600M, "600m", NULL, 0, 600000000, },
|
||||
{ HI3559AV100_FIXED_568M, "568m", NULL, 0, 568000000, },
|
||||
{ HI3559AV100_FIXED_500M, "500m", NULL, 0, 500000000, },
|
||||
{ HI3559AV100_FIXED_475M, "475m", NULL, 0, 475000000, },
|
||||
{ HI3559AV100_FIXED_428M, "428m", NULL, 0, 428000000, },
|
||||
{ HI3559AV100_FIXED_400M, "400m", NULL, 0, 400000000, },
|
||||
{ HI3559AV100_FIXED_396M, "396m", NULL, 0, 396000000, },
|
||||
{ HI3559AV100_FIXED_300M, "300m", NULL, 0, 300000000, },
|
||||
{ HI3559AV100_FIXED_250M, "250m", NULL, 0, 250000000, },
|
||||
{ HI3559AV100_FIXED_200M, "200m", NULL, 0, 200000000, },
|
||||
{ HI3559AV100_FIXED_198M, "198m", NULL, 0, 198000000, },
|
||||
{ HI3559AV100_FIXED_187p5M, "187p5m", NULL, 0, 187500000, },
|
||||
{ HI3559AV100_FIXED_150M, "150m", NULL, 0, 150000000, },
|
||||
{ HI3559AV100_FIXED_148p5M, "148p5m", NULL, 0, 1485000000, },
|
||||
{ HI3559AV100_FIXED_125M, "125m", NULL, 0, 125000000, },
|
||||
{ HI3559AV100_FIXED_107M, "107m", NULL, 0, 107000000, },
|
||||
{ HI3559AV100_FIXED_100M, "100m", NULL, 0, 100000000, },
|
||||
{ HI3559AV100_FIXED_99M, "99m", NULL, 0, 99000000, },
|
||||
{ HI3559AV100_FIXED_75M, "75m", NULL, 0, 75000000, },
|
||||
{ HI3559AV100_FIXED_74p25M, "74p25m", NULL, 0, 74250000, },
|
||||
{ HI3559AV100_FIXED_72M, "72m", NULL, 0, 72000000, },
|
||||
{ HI3559AV100_FIXED_60M, "60m", NULL, 0, 60000000, },
|
||||
{ HI3559AV100_FIXED_54M, "54m", NULL, 0, 54000000, },
|
||||
{ HI3559AV100_FIXED_50M, "50m", NULL, 0, 50000000, },
|
||||
{ HI3559AV100_FIXED_49p5M, "49p5m", NULL, 0, 49500000, },
|
||||
{ HI3559AV100_FIXED_37p125M, "37p125m", NULL, 0, 37125000, },
|
||||
{ HI3559AV100_FIXED_36M, "36m", NULL, 0, 36000000, },
|
||||
{ HI3559AV100_FIXED_32p4M, "32p4m", NULL, 0, 32400000, },
|
||||
{ HI3559AV100_FIXED_27M, "27m", NULL, 0, 27000000, },
|
||||
{ HI3559AV100_FIXED_25M, "25m", NULL, 0, 25000000, },
|
||||
{ HI3559AV100_FIXED_24M, "24m", NULL, 0, 24000000, },
|
||||
{ HI3559AV100_FIXED_12M, "12m", NULL, 0, 12000000, },
|
||||
{ HI3559AV100_FIXED_3M, "3m", NULL, 0, 3000000, },
|
||||
{ HI3559AV100_FIXED_1p6M, "1p6m", NULL, 0, 1600000, },
|
||||
{ HI3559AV100_FIXED_400K, "400k", NULL, 0, 400000, },
|
||||
{ HI3559AV100_FIXED_100K, "100k", NULL, 0, 100000, },
|
||||
};
|
||||
|
||||
|
||||
static const char *fmc_mux_p[] __initconst = {
|
||||
"24m", "75m", "125m", "150m", "200m", "250m", "300m", "400m"
|
||||
};
|
||||
|
||||
static const char *mmc_mux_p[] __initconst = {
|
||||
"100k", "25m", "49p5m", "99m", "187p5m", "150m", "198m", "400k"
|
||||
};
|
||||
|
||||
static const char *sysapb_mux_p[] __initconst = {
|
||||
"24m", "50m",
|
||||
};
|
||||
|
||||
static const char *sysbus_mux_p[] __initconst = {
|
||||
"24m", "300m"
|
||||
};
|
||||
|
||||
static const char *uart_mux_p[] __initconst = { "50m", "24m", "3m" };
|
||||
|
||||
static const char *a73_clksel_mux_p[] __initconst = {
|
||||
"24m", "apll", "1000m"
|
||||
};
|
||||
|
||||
static const u32 fmc_mux_table[] = { 0, 1, 2, 3, 4, 5, 6, 7 };
|
||||
static const u32 mmc_mux_table[] = { 0, 1, 2, 3, 4, 5, 6, 7 };
|
||||
static const u32 sysapb_mux_table[] = { 0, 1 };
|
||||
static const u32 sysbus_mux_table[] = { 0, 1 };
|
||||
static const u32 uart_mux_table[] = { 0, 1, 2 };
|
||||
static const u32 a73_clksel_mux_table[] = { 0, 1, 2 };
|
||||
|
||||
static struct hisi_mux_clock hi3559av100_mux_clks_crg[] __initdata = {
|
||||
{
|
||||
HI3559AV100_FMC_MUX, "fmc_mux", fmc_mux_p, ARRAY_SIZE(fmc_mux_p),
|
||||
CLK_SET_RATE_PARENT, 0x170, 2, 3, 0, fmc_mux_table,
|
||||
},
|
||||
{
|
||||
HI3559AV100_MMC0_MUX, "mmc0_mux", mmc_mux_p, ARRAY_SIZE(mmc_mux_p),
|
||||
CLK_SET_RATE_PARENT, 0x1a8, 24, 3, 0, mmc_mux_table,
|
||||
},
|
||||
{
|
||||
HI3559AV100_MMC1_MUX, "mmc1_mux", mmc_mux_p, ARRAY_SIZE(mmc_mux_p),
|
||||
CLK_SET_RATE_PARENT, 0x1ec, 24, 3, 0, mmc_mux_table,
|
||||
},
|
||||
|
||||
{
|
||||
HI3559AV100_MMC2_MUX, "mmc2_mux", mmc_mux_p, ARRAY_SIZE(mmc_mux_p),
|
||||
CLK_SET_RATE_PARENT, 0x214, 24, 3, 0, mmc_mux_table,
|
||||
},
|
||||
|
||||
{
|
||||
HI3559AV100_MMC3_MUX, "mmc3_mux", mmc_mux_p, ARRAY_SIZE(mmc_mux_p),
|
||||
CLK_SET_RATE_PARENT, 0x23c, 24, 3, 0, mmc_mux_table,
|
||||
},
|
||||
|
||||
{
|
||||
HI3559AV100_SYSAPB_MUX, "sysapb_mux", sysapb_mux_p, ARRAY_SIZE(sysapb_mux_p),
|
||||
CLK_SET_RATE_PARENT, 0xe8, 3, 1, 0, sysapb_mux_table
|
||||
},
|
||||
|
||||
{
|
||||
HI3559AV100_SYSBUS_MUX, "sysbus_mux", sysbus_mux_p, ARRAY_SIZE(sysbus_mux_p),
|
||||
CLK_SET_RATE_PARENT, 0xe8, 0, 1, 0, sysbus_mux_table
|
||||
},
|
||||
|
||||
{
|
||||
HI3559AV100_UART_MUX, "uart_mux", uart_mux_p, ARRAY_SIZE(uart_mux_p),
|
||||
CLK_SET_RATE_PARENT, 0x198, 28, 2, 0, uart_mux_table
|
||||
},
|
||||
|
||||
{
|
||||
HI3559AV100_A73_MUX, "a73_mux", a73_clksel_mux_p, ARRAY_SIZE(a73_clksel_mux_p),
|
||||
CLK_SET_RATE_PARENT, 0xe4, 0, 2, 0, a73_clksel_mux_table
|
||||
},
|
||||
};
|
||||
|
||||
static struct hisi_gate_clock hi3559av100_gate_clks[] __initdata = {
|
||||
{
|
||||
HI3559AV100_FMC_CLK, "clk_fmc", "fmc_mux",
|
||||
CLK_SET_RATE_PARENT, 0x170, 1, 0,
|
||||
},
|
||||
{
|
||||
HI3559AV100_MMC0_CLK, "clk_mmc0", "mmc0_mux",
|
||||
CLK_SET_RATE_PARENT, 0x1a8, 28, 0,
|
||||
},
|
||||
{
|
||||
HI3559AV100_MMC1_CLK, "clk_mmc1", "mmc1_mux",
|
||||
CLK_SET_RATE_PARENT, 0x1ec, 28, 0,
|
||||
},
|
||||
{
|
||||
HI3559AV100_MMC2_CLK, "clk_mmc2", "mmc2_mux",
|
||||
CLK_SET_RATE_PARENT, 0x214, 28, 0,
|
||||
},
|
||||
{
|
||||
HI3559AV100_MMC3_CLK, "clk_mmc3", "mmc3_mux",
|
||||
CLK_SET_RATE_PARENT, 0x23c, 28, 0,
|
||||
},
|
||||
{
|
||||
HI3559AV100_UART0_CLK, "clk_uart0", "uart_mux",
|
||||
CLK_SET_RATE_PARENT, 0x198, 23, 0,
|
||||
},
|
||||
{
|
||||
HI3559AV100_UART1_CLK, "clk_uart1", "uart_mux",
|
||||
CLK_SET_RATE_PARENT, 0x198, 24, 0,
|
||||
},
|
||||
{
|
||||
HI3559AV100_UART2_CLK, "clk_uart2", "uart_mux",
|
||||
CLK_SET_RATE_PARENT, 0x198, 25, 0,
|
||||
},
|
||||
{
|
||||
HI3559AV100_UART3_CLK, "clk_uart3", "uart_mux",
|
||||
CLK_SET_RATE_PARENT, 0x198, 26, 0,
|
||||
},
|
||||
{
|
||||
HI3559AV100_UART4_CLK, "clk_uart4", "uart_mux",
|
||||
CLK_SET_RATE_PARENT, 0x198, 27, 0,
|
||||
},
|
||||
{
|
||||
HI3559AV100_ETH_CLK, "clk_eth", NULL,
|
||||
CLK_SET_RATE_PARENT, 0x0174, 1, 0,
|
||||
},
|
||||
{
|
||||
HI3559AV100_ETH_MACIF_CLK, "clk_eth_macif", NULL,
|
||||
CLK_SET_RATE_PARENT, 0x0174, 5, 0,
|
||||
},
|
||||
{
|
||||
HI3559AV100_ETH1_CLK, "clk_eth1", NULL,
|
||||
CLK_SET_RATE_PARENT, 0x0174, 3, 0,
|
||||
},
|
||||
{
|
||||
HI3559AV100_ETH1_MACIF_CLK, "clk_eth1_macif", NULL,
|
||||
CLK_SET_RATE_PARENT, 0x0174, 7, 0,
|
||||
},
|
||||
{
|
||||
HI3559AV100_I2C0_CLK, "clk_i2c0", "50m",
|
||||
CLK_SET_RATE_PARENT, 0x01a0, 16, 0,
|
||||
},
|
||||
{
|
||||
HI3559AV100_I2C1_CLK, "clk_i2c1", "50m",
|
||||
CLK_SET_RATE_PARENT, 0x01a0, 17, 0,
|
||||
},
|
||||
{
|
||||
HI3559AV100_I2C2_CLK, "clk_i2c2", "50m",
|
||||
CLK_SET_RATE_PARENT, 0x01a0, 18, 0,
|
||||
},
|
||||
{
|
||||
HI3559AV100_I2C3_CLK, "clk_i2c3", "50m",
|
||||
CLK_SET_RATE_PARENT, 0x01a0, 19, 0,
|
||||
},
|
||||
{
|
||||
HI3559AV100_I2C4_CLK, "clk_i2c4", "50m",
|
||||
CLK_SET_RATE_PARENT, 0x01a0, 20, 0,
|
||||
},
|
||||
{
|
||||
HI3559AV100_I2C5_CLK, "clk_i2c5", "50m",
|
||||
CLK_SET_RATE_PARENT, 0x01a0, 21, 0,
|
||||
},
|
||||
{
|
||||
HI3559AV100_I2C6_CLK, "clk_i2c6", "50m",
|
||||
CLK_SET_RATE_PARENT, 0x01a0, 22, 0,
|
||||
},
|
||||
{
|
||||
HI3559AV100_I2C7_CLK, "clk_i2c7", "50m",
|
||||
CLK_SET_RATE_PARENT, 0x01a0, 23, 0,
|
||||
},
|
||||
{
|
||||
HI3559AV100_I2C8_CLK, "clk_i2c8", "50m",
|
||||
CLK_SET_RATE_PARENT, 0x01a0, 24, 0,
|
||||
},
|
||||
{
|
||||
HI3559AV100_I2C9_CLK, "clk_i2c9", "50m",
|
||||
CLK_SET_RATE_PARENT, 0x01a0, 25, 0,
|
||||
},
|
||||
{
|
||||
HI3559AV100_I2C10_CLK, "clk_i2c10", "50m",
|
||||
CLK_SET_RATE_PARENT, 0x01a0, 26, 0,
|
||||
},
|
||||
{
|
||||
HI3559AV100_I2C11_CLK, "clk_i2c11", "50m",
|
||||
CLK_SET_RATE_PARENT, 0x01a0, 27, 0,
|
||||
},
|
||||
{
|
||||
HI3559AV100_SPI0_CLK, "clk_spi0", "100m",
|
||||
CLK_SET_RATE_PARENT, 0x0198, 16, 0,
|
||||
},
|
||||
{
|
||||
HI3559AV100_SPI1_CLK, "clk_spi1", "100m",
|
||||
CLK_SET_RATE_PARENT, 0x0198, 17, 0,
|
||||
},
|
||||
{
|
||||
HI3559AV100_SPI2_CLK, "clk_spi2", "100m",
|
||||
CLK_SET_RATE_PARENT, 0x0198, 18, 0,
|
||||
},
|
||||
{
|
||||
HI3559AV100_SPI3_CLK, "clk_spi3", "100m",
|
||||
CLK_SET_RATE_PARENT, 0x0198, 19, 0,
|
||||
},
|
||||
{
|
||||
HI3559AV100_SPI4_CLK, "clk_spi4", "100m",
|
||||
CLK_SET_RATE_PARENT, 0x0198, 20, 0,
|
||||
},
|
||||
{
|
||||
HI3559AV100_SPI5_CLK, "clk_spi5", "100m",
|
||||
CLK_SET_RATE_PARENT, 0x0198, 21, 0,
|
||||
},
|
||||
{
|
||||
HI3559AV100_SPI6_CLK, "clk_spi6", "100m",
|
||||
CLK_SET_RATE_PARENT, 0x0198, 22, 0,
|
||||
},
|
||||
{
|
||||
HI3559AV100_EDMAC_AXICLK, "axi_clk_edmac", NULL,
|
||||
CLK_SET_RATE_PARENT, 0x16c, 6, 0,
|
||||
},
|
||||
{
|
||||
HI3559AV100_EDMAC_CLK, "clk_edmac", NULL,
|
||||
CLK_SET_RATE_PARENT, 0x16c, 5, 0,
|
||||
},
|
||||
{
|
||||
HI3559AV100_EDMAC1_AXICLK, "axi_clk_edmac1", NULL,
|
||||
CLK_SET_RATE_PARENT, 0x16c, 9, 0,
|
||||
},
|
||||
{
|
||||
HI3559AV100_EDMAC1_CLK, "clk_edmac1", NULL,
|
||||
CLK_SET_RATE_PARENT, 0x16c, 8, 0,
|
||||
},
|
||||
{
|
||||
HI3559AV100_VDMAC_CLK, "clk_vdmac", NULL,
|
||||
CLK_SET_RATE_PARENT, 0x14c, 5, 0,
|
||||
},
|
||||
};
|
||||
|
||||
static struct hi3559av100_pll_clock hi3559av100_pll_clks[] __initdata = {
|
||||
{
|
||||
HI3559AV100_APLL_CLK, "apll", NULL, 0x0, 0, 24, 24, 3, 28, 3,
|
||||
0x4, 0, 12, 12, 6
|
||||
},
|
||||
{
|
||||
HI3559AV100_GPLL_CLK, "gpll", NULL, 0x20, 0, 24, 24, 3, 28, 3,
|
||||
0x24, 0, 12, 12, 6
|
||||
},
|
||||
};
|
||||
|
||||
#define to_pll_clk(_hw) container_of(_hw, struct hi3559av100_clk_pll, hw)
|
||||
static void hi3559av100_calc_pll(u32 *frac_val, u32 *postdiv1_val,
|
||||
u32 *postdiv2_val,
|
||||
u32 *fbdiv_val, u32 *refdiv_val, u64 rate)
|
||||
{
|
||||
u64 rem;
|
||||
|
||||
*postdiv1_val = 2;
|
||||
*postdiv2_val = 1;
|
||||
|
||||
rate = rate * ((*postdiv1_val) * (*postdiv2_val));
|
||||
|
||||
*frac_val = 0;
|
||||
rem = do_div(rate, 1000000);
|
||||
rem = do_div(rate, PLL_MASK_WIDTH);
|
||||
*fbdiv_val = rate;
|
||||
*refdiv_val = 1;
|
||||
rem = rem * (1 << PLL_MASK_WIDTH);
|
||||
do_div(rem, PLL_MASK_WIDTH);
|
||||
*frac_val = rem;
|
||||
}
|
||||
|
||||
static int clk_pll_set_rate(struct clk_hw *hw,
|
||||
unsigned long rate,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct hi3559av100_clk_pll *clk = to_pll_clk(hw);
|
||||
u32 frac_val, postdiv1_val, postdiv2_val, fbdiv_val, refdiv_val;
|
||||
u32 val;
|
||||
|
||||
postdiv1_val = postdiv2_val = 0;
|
||||
|
||||
hi3559av100_calc_pll(&frac_val, &postdiv1_val, &postdiv2_val,
|
||||
&fbdiv_val, &refdiv_val, (u64)rate);
|
||||
|
||||
val = readl_relaxed(clk->ctrl_reg1);
|
||||
val &= ~(((1 << clk->frac_width) - 1) << clk->frac_shift);
|
||||
val &= ~(((1 << clk->postdiv1_width) - 1) << clk->postdiv1_shift);
|
||||
val &= ~(((1 << clk->postdiv2_width) - 1) << clk->postdiv2_shift);
|
||||
|
||||
val |= frac_val << clk->frac_shift;
|
||||
val |= postdiv1_val << clk->postdiv1_shift;
|
||||
val |= postdiv2_val << clk->postdiv2_shift;
|
||||
writel_relaxed(val, clk->ctrl_reg1);
|
||||
|
||||
val = readl_relaxed(clk->ctrl_reg2);
|
||||
val &= ~(((1 << clk->fbdiv_width) - 1) << clk->fbdiv_shift);
|
||||
val &= ~(((1 << clk->refdiv_width) - 1) << clk->refdiv_shift);
|
||||
|
||||
val |= fbdiv_val << clk->fbdiv_shift;
|
||||
val |= refdiv_val << clk->refdiv_shift;
|
||||
writel_relaxed(val, clk->ctrl_reg2);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned long clk_pll_recalc_rate(struct clk_hw *hw,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct hi3559av100_clk_pll *clk = to_pll_clk(hw);
|
||||
u64 frac_val, fbdiv_val, refdiv_val;
|
||||
u32 postdiv1_val, postdiv2_val;
|
||||
u32 val;
|
||||
u64 tmp, rate;
|
||||
|
||||
val = readl_relaxed(clk->ctrl_reg1);
|
||||
val = val >> clk->frac_shift;
|
||||
val &= ((1 << clk->frac_width) - 1);
|
||||
frac_val = val;
|
||||
|
||||
val = readl_relaxed(clk->ctrl_reg1);
|
||||
val = val >> clk->postdiv1_shift;
|
||||
val &= ((1 << clk->postdiv1_width) - 1);
|
||||
postdiv1_val = val;
|
||||
|
||||
val = readl_relaxed(clk->ctrl_reg1);
|
||||
val = val >> clk->postdiv2_shift;
|
||||
val &= ((1 << clk->postdiv2_width) - 1);
|
||||
postdiv2_val = val;
|
||||
|
||||
val = readl_relaxed(clk->ctrl_reg2);
|
||||
val = val >> clk->fbdiv_shift;
|
||||
val &= ((1 << clk->fbdiv_width) - 1);
|
||||
fbdiv_val = val;
|
||||
|
||||
val = readl_relaxed(clk->ctrl_reg2);
|
||||
val = val >> clk->refdiv_shift;
|
||||
val &= ((1 << clk->refdiv_width) - 1);
|
||||
refdiv_val = val;
|
||||
|
||||
/* rate = 24000000 * (fbdiv + frac / (1<<24) ) / refdiv */
|
||||
rate = 0;
|
||||
tmp = 24000000 * fbdiv_val + (24000000 * frac_val) / (1 << 24);
|
||||
rate += tmp;
|
||||
do_div(rate, refdiv_val);
|
||||
do_div(rate, postdiv1_val * postdiv2_val);
|
||||
|
||||
return rate;
|
||||
}
|
||||
|
||||
static const struct clk_ops hisi_clk_pll_ops = {
|
||||
.set_rate = clk_pll_set_rate,
|
||||
.recalc_rate = clk_pll_recalc_rate,
|
||||
};
|
||||
|
||||
static void hisi_clk_register_pll(struct hi3559av100_pll_clock *clks,
|
||||
int nums, struct hisi_clock_data *data, struct device *dev)
|
||||
{
|
||||
void __iomem *base = data->base;
|
||||
struct hi3559av100_clk_pll *p_clk = NULL;
|
||||
struct clk *clk = NULL;
|
||||
struct clk_init_data init;
|
||||
int i;
|
||||
|
||||
p_clk = devm_kzalloc(dev, sizeof(*p_clk) * nums, GFP_KERNEL);
|
||||
|
||||
if (!p_clk)
|
||||
return;
|
||||
|
||||
for (i = 0; i < nums; i++) {
|
||||
init.name = clks[i].name;
|
||||
init.flags = 0;
|
||||
init.parent_names =
|
||||
(clks[i].parent_name ? &clks[i].parent_name : NULL);
|
||||
init.num_parents = (clks[i].parent_name ? 1 : 0);
|
||||
init.ops = &hisi_clk_pll_ops;
|
||||
|
||||
p_clk->ctrl_reg1 = base + clks[i].ctrl_reg1;
|
||||
p_clk->frac_shift = clks[i].frac_shift;
|
||||
p_clk->frac_width = clks[i].frac_width;
|
||||
p_clk->postdiv1_shift = clks[i].postdiv1_shift;
|
||||
p_clk->postdiv1_width = clks[i].postdiv1_width;
|
||||
p_clk->postdiv2_shift = clks[i].postdiv2_shift;
|
||||
p_clk->postdiv2_width = clks[i].postdiv2_width;
|
||||
|
||||
p_clk->ctrl_reg2 = base + clks[i].ctrl_reg2;
|
||||
p_clk->fbdiv_shift = clks[i].fbdiv_shift;
|
||||
p_clk->fbdiv_width = clks[i].fbdiv_width;
|
||||
p_clk->refdiv_shift = clks[i].refdiv_shift;
|
||||
p_clk->refdiv_width = clks[i].refdiv_width;
|
||||
p_clk->hw.init = &init;
|
||||
|
||||
clk = clk_register(NULL, &p_clk->hw);
|
||||
if (IS_ERR(clk)) {
|
||||
devm_kfree(dev, p_clk);
|
||||
dev_err(dev, "%s: failed to register clock %s\n",
|
||||
__func__, clks[i].name);
|
||||
continue;
|
||||
}
|
||||
|
||||
data->clk_data.clks[clks[i].id] = clk;
|
||||
p_clk++;
|
||||
}
|
||||
}
|
||||
|
||||
static __init struct hisi_clock_data *hi3559av100_clk_register(
|
||||
struct platform_device *pdev)
|
||||
{
|
||||
struct hisi_clock_data *clk_data;
|
||||
int ret;
|
||||
|
||||
clk_data = hisi_clk_alloc(pdev, HI3559AV100_CRG_NR_CLKS);
|
||||
if (!clk_data)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
ret = hisi_clk_register_fixed_rate(hi3559av100_fixed_rate_clks_crg,
|
||||
ARRAY_SIZE(hi3559av100_fixed_rate_clks_crg), clk_data);
|
||||
if (ret)
|
||||
return ERR_PTR(ret);
|
||||
|
||||
hisi_clk_register_pll(hi3559av100_pll_clks,
|
||||
ARRAY_SIZE(hi3559av100_pll_clks), clk_data, &pdev->dev);
|
||||
|
||||
ret = hisi_clk_register_mux(hi3559av100_mux_clks_crg,
|
||||
ARRAY_SIZE(hi3559av100_mux_clks_crg), clk_data);
|
||||
if (ret)
|
||||
goto unregister_fixed_rate;
|
||||
|
||||
ret = hisi_clk_register_gate(hi3559av100_gate_clks,
|
||||
ARRAY_SIZE(hi3559av100_gate_clks), clk_data);
|
||||
if (ret)
|
||||
goto unregister_mux;
|
||||
|
||||
ret = of_clk_add_provider(pdev->dev.of_node,
|
||||
of_clk_src_onecell_get, &clk_data->clk_data);
|
||||
if (ret)
|
||||
goto unregister_gate;
|
||||
|
||||
return clk_data;
|
||||
|
||||
unregister_gate:
|
||||
hisi_clk_unregister_gate(hi3559av100_gate_clks,
|
||||
ARRAY_SIZE(hi3559av100_gate_clks), clk_data);
|
||||
unregister_mux:
|
||||
hisi_clk_unregister_mux(hi3559av100_mux_clks_crg,
|
||||
ARRAY_SIZE(hi3559av100_mux_clks_crg), clk_data);
|
||||
unregister_fixed_rate:
|
||||
hisi_clk_unregister_fixed_rate(hi3559av100_fixed_rate_clks_crg,
|
||||
ARRAY_SIZE(hi3559av100_fixed_rate_clks_crg), clk_data);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
static __init void hi3559av100_clk_unregister(struct platform_device *pdev)
|
||||
{
|
||||
struct hisi_crg_dev *crg = platform_get_drvdata(pdev);
|
||||
|
||||
of_clk_del_provider(pdev->dev.of_node);
|
||||
|
||||
hisi_clk_unregister_gate(hi3559av100_gate_clks,
|
||||
ARRAY_SIZE(hi3559av100_gate_clks), crg->clk_data);
|
||||
hisi_clk_unregister_mux(hi3559av100_mux_clks_crg,
|
||||
ARRAY_SIZE(hi3559av100_mux_clks_crg), crg->clk_data);
|
||||
hisi_clk_unregister_fixed_rate(hi3559av100_fixed_rate_clks_crg,
|
||||
ARRAY_SIZE(hi3559av100_fixed_rate_clks_crg), crg->clk_data);
|
||||
}
|
||||
|
||||
static const struct hisi_crg_funcs hi3559av100_crg_funcs = {
|
||||
.register_clks = hi3559av100_clk_register,
|
||||
.unregister_clks = hi3559av100_clk_unregister,
|
||||
};
|
||||
|
||||
static struct hisi_fixed_rate_clock hi3559av100_shub_fixed_rate_clks[]
|
||||
__initdata = {
|
||||
{ HI3559AV100_SHUB_SOURCE_SOC_24M, "clk_source_24M", NULL, 0, 24000000UL, },
|
||||
{ HI3559AV100_SHUB_SOURCE_SOC_200M, "clk_source_200M", NULL, 0, 200000000UL, },
|
||||
{ HI3559AV100_SHUB_SOURCE_SOC_300M, "clk_source_300M", NULL, 0, 300000000UL, },
|
||||
{ HI3559AV100_SHUB_SOURCE_PLL, "clk_source_PLL", NULL, 0, 192000000UL, },
|
||||
{ HI3559AV100_SHUB_I2C0_CLK, "clk_shub_i2c0", NULL, 0, 48000000UL, },
|
||||
{ HI3559AV100_SHUB_I2C1_CLK, "clk_shub_i2c1", NULL, 0, 48000000UL, },
|
||||
{ HI3559AV100_SHUB_I2C2_CLK, "clk_shub_i2c2", NULL, 0, 48000000UL, },
|
||||
{ HI3559AV100_SHUB_I2C3_CLK, "clk_shub_i2c3", NULL, 0, 48000000UL, },
|
||||
{ HI3559AV100_SHUB_I2C4_CLK, "clk_shub_i2c4", NULL, 0, 48000000UL, },
|
||||
{ HI3559AV100_SHUB_I2C5_CLK, "clk_shub_i2c5", NULL, 0, 48000000UL, },
|
||||
{ HI3559AV100_SHUB_I2C6_CLK, "clk_shub_i2c6", NULL, 0, 48000000UL, },
|
||||
{ HI3559AV100_SHUB_I2C7_CLK, "clk_shub_i2c7", NULL, 0, 48000000UL, },
|
||||
{ HI3559AV100_SHUB_UART_CLK_32K, "clk_uart_32K", NULL, 0, 32000UL, },
|
||||
};
|
||||
|
||||
/* shub mux clk */
|
||||
static u32 shub_source_clk_mux_table[] = {0, 1, 2, 3};
|
||||
static const char *shub_source_clk_mux_p[] __initconst = {
|
||||
"clk_source_24M", "clk_source_200M", "clk_source_300M", "clk_source_PLL"
|
||||
};
|
||||
|
||||
static u32 shub_uart_source_clk_mux_table[] = {0, 1, 2, 3};
|
||||
static const char *shub_uart_source_clk_mux_p[] __initconst = {
|
||||
"clk_uart_32K", "clk_uart_div_clk", "clk_uart_div_clk", "clk_source_24M"
|
||||
};
|
||||
|
||||
static struct hisi_mux_clock hi3559av100_shub_mux_clks[] __initdata = {
|
||||
{
|
||||
HI3559AV100_SHUB_SOURCE_CLK, "shub_clk", shub_source_clk_mux_p,
|
||||
ARRAY_SIZE(shub_source_clk_mux_p),
|
||||
0, 0x0, 0, 2, 0, shub_source_clk_mux_table,
|
||||
},
|
||||
|
||||
{
|
||||
HI3559AV100_SHUB_UART_SOURCE_CLK, "shub_uart_source_clk",
|
||||
shub_uart_source_clk_mux_p, ARRAY_SIZE(shub_uart_source_clk_mux_p),
|
||||
0, 0x1c, 28, 2, 0, shub_uart_source_clk_mux_table,
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
/* shub div clk */
|
||||
static struct clk_div_table shub_spi_clk_table[] = {{0, 8}, {1, 4}, {2, 2}};
|
||||
static struct clk_div_table shub_uart_div_clk_table[] = {{1, 8}, {2, 4}};
|
||||
|
||||
static struct hisi_divider_clock hi3559av100_shub_div_clks[] __initdata = {
|
||||
{ HI3559AV100_SHUB_SPI_SOURCE_CLK, "clk_spi_clk", "shub_clk", 0, 0x20, 24, 2,
|
||||
CLK_DIVIDER_ALLOW_ZERO, shub_spi_clk_table,
|
||||
},
|
||||
{ HI3559AV100_SHUB_UART_DIV_CLK, "clk_uart_div_clk", "shub_clk", 0, 0x1c, 28, 2,
|
||||
CLK_DIVIDER_ALLOW_ZERO, shub_uart_div_clk_table,
|
||||
},
|
||||
};
|
||||
|
||||
/* shub gate clk */
|
||||
static struct hisi_gate_clock hi3559av100_shub_gate_clks[] __initdata = {
|
||||
{
|
||||
HI3559AV100_SHUB_SPI0_CLK, "clk_shub_spi0", "clk_spi_clk",
|
||||
0, 0x20, 1, 0,
|
||||
},
|
||||
{
|
||||
HI3559AV100_SHUB_SPI1_CLK, "clk_shub_spi1", "clk_spi_clk",
|
||||
0, 0x20, 5, 0,
|
||||
},
|
||||
{
|
||||
HI3559AV100_SHUB_SPI2_CLK, "clk_shub_spi2", "clk_spi_clk",
|
||||
0, 0x20, 9, 0,
|
||||
},
|
||||
|
||||
{
|
||||
HI3559AV100_SHUB_UART0_CLK, "clk_shub_uart0", "shub_uart_source_clk",
|
||||
0, 0x1c, 1, 0,
|
||||
},
|
||||
{
|
||||
HI3559AV100_SHUB_UART1_CLK, "clk_shub_uart1", "shub_uart_source_clk",
|
||||
0, 0x1c, 5, 0,
|
||||
},
|
||||
{
|
||||
HI3559AV100_SHUB_UART2_CLK, "clk_shub_uart2", "shub_uart_source_clk",
|
||||
0, 0x1c, 9, 0,
|
||||
},
|
||||
{
|
||||
HI3559AV100_SHUB_UART3_CLK, "clk_shub_uart3", "shub_uart_source_clk",
|
||||
0, 0x1c, 13, 0,
|
||||
},
|
||||
{
|
||||
HI3559AV100_SHUB_UART4_CLK, "clk_shub_uart4", "shub_uart_source_clk",
|
||||
0, 0x1c, 17, 0,
|
||||
},
|
||||
{
|
||||
HI3559AV100_SHUB_UART5_CLK, "clk_shub_uart5", "shub_uart_source_clk",
|
||||
0, 0x1c, 21, 0,
|
||||
},
|
||||
{
|
||||
HI3559AV100_SHUB_UART6_CLK, "clk_shub_uart6", "shub_uart_source_clk",
|
||||
0, 0x1c, 25, 0,
|
||||
},
|
||||
|
||||
{
|
||||
HI3559AV100_SHUB_EDMAC_CLK, "clk_shub_dmac", "shub_clk",
|
||||
0, 0x24, 4, 0,
|
||||
},
|
||||
};
|
||||
|
||||
static int hi3559av100_shub_default_clk_set(void)
|
||||
{
|
||||
void __iomem *crg_base;
|
||||
unsigned int val;
|
||||
|
||||
crg_base = ioremap(CRG_BASE_ADDR, SZ_4K);
|
||||
|
||||
/* SSP: 192M/2 */
|
||||
val = readl_relaxed(crg_base + 0x20);
|
||||
val |= (0x2 << 24);
|
||||
writel_relaxed(val, crg_base + 0x20);
|
||||
|
||||
/* UART: 192M/8 */
|
||||
val = readl_relaxed(crg_base + 0x1C);
|
||||
val |= (0x1 << 28);
|
||||
writel_relaxed(val, crg_base + 0x1C);
|
||||
|
||||
iounmap(crg_base);
|
||||
crg_base = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static __init struct hisi_clock_data *hi3559av100_shub_clk_register(
|
||||
struct platform_device *pdev)
|
||||
{
|
||||
struct hisi_clock_data *clk_data = NULL;
|
||||
int ret;
|
||||
|
||||
hi3559av100_shub_default_clk_set();
|
||||
|
||||
clk_data = hisi_clk_alloc(pdev, HI3559AV100_SHUB_NR_CLKS);
|
||||
if (!clk_data)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
ret = hisi_clk_register_fixed_rate(hi3559av100_shub_fixed_rate_clks,
|
||||
ARRAY_SIZE(hi3559av100_shub_fixed_rate_clks), clk_data);
|
||||
if (ret)
|
||||
return ERR_PTR(ret);
|
||||
|
||||
ret = hisi_clk_register_mux(hi3559av100_shub_mux_clks,
|
||||
ARRAY_SIZE(hi3559av100_shub_mux_clks), clk_data);
|
||||
if (ret)
|
||||
goto unregister_fixed_rate;
|
||||
|
||||
ret = hisi_clk_register_divider(hi3559av100_shub_div_clks,
|
||||
ARRAY_SIZE(hi3559av100_shub_div_clks), clk_data);
|
||||
if (ret)
|
||||
goto unregister_mux;
|
||||
|
||||
ret = hisi_clk_register_gate(hi3559av100_shub_gate_clks,
|
||||
ARRAY_SIZE(hi3559av100_shub_gate_clks), clk_data);
|
||||
if (ret)
|
||||
goto unregister_factor;
|
||||
|
||||
ret = of_clk_add_provider(pdev->dev.of_node,
|
||||
of_clk_src_onecell_get, &clk_data->clk_data);
|
||||
if (ret)
|
||||
goto unregister_gate;
|
||||
|
||||
return clk_data;
|
||||
|
||||
unregister_gate:
|
||||
hisi_clk_unregister_gate(hi3559av100_shub_gate_clks,
|
||||
ARRAY_SIZE(hi3559av100_shub_gate_clks), clk_data);
|
||||
unregister_factor:
|
||||
hisi_clk_unregister_divider(hi3559av100_shub_div_clks,
|
||||
ARRAY_SIZE(hi3559av100_shub_div_clks), clk_data);
|
||||
unregister_mux:
|
||||
hisi_clk_unregister_mux(hi3559av100_shub_mux_clks,
|
||||
ARRAY_SIZE(hi3559av100_shub_mux_clks), clk_data);
|
||||
unregister_fixed_rate:
|
||||
hisi_clk_unregister_fixed_rate(hi3559av100_shub_fixed_rate_clks,
|
||||
ARRAY_SIZE(hi3559av100_shub_fixed_rate_clks), clk_data);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
static __init void hi3559av100_shub_clk_unregister(struct platform_device *pdev)
|
||||
{
|
||||
struct hisi_crg_dev *crg = platform_get_drvdata(pdev);
|
||||
|
||||
of_clk_del_provider(pdev->dev.of_node);
|
||||
|
||||
hisi_clk_unregister_gate(hi3559av100_shub_gate_clks,
|
||||
ARRAY_SIZE(hi3559av100_shub_gate_clks), crg->clk_data);
|
||||
hisi_clk_unregister_divider(hi3559av100_shub_div_clks,
|
||||
ARRAY_SIZE(hi3559av100_shub_div_clks), crg->clk_data);
|
||||
hisi_clk_unregister_mux(hi3559av100_shub_mux_clks,
|
||||
ARRAY_SIZE(hi3559av100_shub_mux_clks), crg->clk_data);
|
||||
hisi_clk_unregister_fixed_rate(hi3559av100_shub_fixed_rate_clks,
|
||||
ARRAY_SIZE(hi3559av100_shub_fixed_rate_clks), crg->clk_data);
|
||||
}
|
||||
|
||||
static const struct hisi_crg_funcs hi3559av100_shub_crg_funcs = {
|
||||
.register_clks = hi3559av100_shub_clk_register,
|
||||
.unregister_clks = hi3559av100_shub_clk_unregister,
|
||||
};
|
||||
|
||||
static const struct of_device_id hi3559av100_crg_match_table[] = {
|
||||
{
|
||||
.compatible = "hisilicon,hi3559av100-clock",
|
||||
.data = &hi3559av100_crg_funcs
|
||||
},
|
||||
{
|
||||
.compatible = "hisilicon,hi3559av100-shub-clock",
|
||||
.data = &hi3559av100_shub_crg_funcs
|
||||
},
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, hi3559av100_crg_match_table);
|
||||
|
||||
static int hi3559av100_crg_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct hisi_crg_dev *crg;
|
||||
|
||||
crg = devm_kmalloc(&pdev->dev, sizeof(*crg), GFP_KERNEL);
|
||||
if (!crg)
|
||||
return -ENOMEM;
|
||||
|
||||
crg->funcs = of_device_get_match_data(&pdev->dev);
|
||||
if (!crg->funcs)
|
||||
return -ENOENT;
|
||||
|
||||
crg->rstc = hisi_reset_init(pdev);
|
||||
if (!crg->rstc)
|
||||
return -ENOMEM;
|
||||
|
||||
crg->clk_data = crg->funcs->register_clks(pdev);
|
||||
if (IS_ERR(crg->clk_data)) {
|
||||
hisi_reset_exit(crg->rstc);
|
||||
return PTR_ERR(crg->clk_data);
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, crg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hi3559av100_crg_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct hisi_crg_dev *crg = platform_get_drvdata(pdev);
|
||||
|
||||
hisi_reset_exit(crg->rstc);
|
||||
crg->funcs->unregister_clks(pdev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver hi3559av100_crg_driver = {
|
||||
.probe = hi3559av100_crg_probe,
|
||||
.remove = hi3559av100_crg_remove,
|
||||
.driver = {
|
||||
.name = "hi3559av100-clock",
|
||||
.of_match_table = hi3559av100_crg_match_table,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init hi3559av100_crg_init(void)
|
||||
{
|
||||
return platform_driver_register(&hi3559av100_crg_driver);
|
||||
}
|
||||
core_initcall(hi3559av100_crg_init);
|
||||
|
||||
static void __exit hi3559av100_crg_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&hi3559av100_crg_driver);
|
||||
}
|
||||
module_exit(hi3559av100_crg_exit);
|
||||
|
||||
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_DESCRIPTION("HiSilicon Hi3559AV100 CRG Driver");
|
|
@ -162,7 +162,7 @@ int hisi_clk_register_mux(const struct hisi_mux_clock *clks,
|
|||
clks[i].num_parents, clks[i].flags,
|
||||
base + clks[i].offset, clks[i].shift,
|
||||
mask, clks[i].mux_flags,
|
||||
clks[i].table, &hisi_clk_lock);
|
||||
(u32 *)clks[i].table, &hisi_clk_lock);
|
||||
if (IS_ERR(clk)) {
|
||||
pr_err("%s: failed to register clock %s\n",
|
||||
__func__, clks[i].name);
|
||||
|
|
|
@ -50,7 +50,7 @@ struct hisi_mux_clock {
|
|||
u8 shift;
|
||||
u8 width;
|
||||
u8 mux_flags;
|
||||
u32 *table;
|
||||
const u32 *table;
|
||||
const char *alias;
|
||||
};
|
||||
|
||||
|
|
|
@ -16,9 +16,16 @@
|
|||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
|
||||
struct clkgen_clk_out {
|
||||
const char *name;
|
||||
unsigned long flags;
|
||||
};
|
||||
|
||||
struct clkgen_data {
|
||||
unsigned long flags;
|
||||
bool mode;
|
||||
const struct clkgen_clk_out *outputs;
|
||||
const unsigned int outputs_nb;
|
||||
};
|
||||
|
||||
struct flexgen {
|
||||
|
@ -295,6 +302,290 @@ static const struct clkgen_data clkgen_video = {
|
|||
.mode = 1,
|
||||
};
|
||||
|
||||
static const struct clkgen_clk_out clkgen_stih407_a0_clk_out[] = {
|
||||
/* This clk needs to be on so that memory interface is accessible */
|
||||
{ .name = "clk-ic-lmi0", .flags = CLK_IS_CRITICAL },
|
||||
};
|
||||
|
||||
static const struct clkgen_data clkgen_stih407_a0 = {
|
||||
.outputs = clkgen_stih407_a0_clk_out,
|
||||
.outputs_nb = ARRAY_SIZE(clkgen_stih407_a0_clk_out),
|
||||
};
|
||||
|
||||
static const struct clkgen_clk_out clkgen_stih410_a0_clk_out[] = {
|
||||
/* Those clks need to be on so that memory interface is accessible */
|
||||
{ .name = "clk-ic-lmi0", .flags = CLK_IS_CRITICAL },
|
||||
{ .name = "clk-ic-lmi1", .flags = CLK_IS_CRITICAL },
|
||||
};
|
||||
|
||||
static const struct clkgen_data clkgen_stih410_a0 = {
|
||||
.outputs = clkgen_stih410_a0_clk_out,
|
||||
.outputs_nb = ARRAY_SIZE(clkgen_stih410_a0_clk_out),
|
||||
};
|
||||
|
||||
static const struct clkgen_clk_out clkgen_stih407_c0_clk_out[] = {
|
||||
{ .name = "clk-icn-gpu", },
|
||||
{ .name = "clk-fdma", },
|
||||
{ .name = "clk-nand", },
|
||||
{ .name = "clk-hva", },
|
||||
{ .name = "clk-proc-stfe", },
|
||||
{ .name = "clk-proc-tp", },
|
||||
{ .name = "clk-rx-icn-dmu", },
|
||||
{ .name = "clk-rx-icn-hva", },
|
||||
/* This clk needs to be on to keep bus interconnect alive */
|
||||
{ .name = "clk-icn-cpu", .flags = CLK_IS_CRITICAL },
|
||||
/* This clk needs to be on to keep bus interconnect alive */
|
||||
{ .name = "clk-tx-icn-dmu", .flags = CLK_IS_CRITICAL },
|
||||
{ .name = "clk-mmc-0", },
|
||||
{ .name = "clk-mmc-1", },
|
||||
{ .name = "clk-jpegdec", },
|
||||
/* This clk needs to be on to keep A9 running */
|
||||
{ .name = "clk-ext2fa9", .flags = CLK_IS_CRITICAL },
|
||||
{ .name = "clk-ic-bdisp-0", },
|
||||
{ .name = "clk-ic-bdisp-1", },
|
||||
{ .name = "clk-pp-dmu", },
|
||||
{ .name = "clk-vid-dmu", },
|
||||
{ .name = "clk-dss-lpc", },
|
||||
{ .name = "clk-st231-aud-0", },
|
||||
{ .name = "clk-st231-gp-1", },
|
||||
{ .name = "clk-st231-dmu", },
|
||||
/* This clk needs to be on to keep bus interconnect alive */
|
||||
{ .name = "clk-icn-lmi", .flags = CLK_IS_CRITICAL },
|
||||
{ .name = "clk-tx-icn-disp-1", },
|
||||
/* This clk needs to be on to keep bus interconnect alive */
|
||||
{ .name = "clk-icn-sbc", .flags = CLK_IS_CRITICAL },
|
||||
{ .name = "clk-stfe-frc2", },
|
||||
{ .name = "clk-eth-phy", },
|
||||
{ .name = "clk-eth-ref-phyclk", },
|
||||
{ .name = "clk-flash-promip", },
|
||||
{ .name = "clk-main-disp", },
|
||||
{ .name = "clk-aux-disp", },
|
||||
{ .name = "clk-compo-dvp", },
|
||||
};
|
||||
|
||||
static const struct clkgen_data clkgen_stih407_c0 = {
|
||||
.outputs = clkgen_stih407_c0_clk_out,
|
||||
.outputs_nb = ARRAY_SIZE(clkgen_stih407_c0_clk_out),
|
||||
};
|
||||
|
||||
static const struct clkgen_clk_out clkgen_stih410_c0_clk_out[] = {
|
||||
{ .name = "clk-icn-gpu", },
|
||||
{ .name = "clk-fdma", },
|
||||
{ .name = "clk-nand", },
|
||||
{ .name = "clk-hva", },
|
||||
{ .name = "clk-proc-stfe", },
|
||||
{ .name = "clk-proc-tp", },
|
||||
{ .name = "clk-rx-icn-dmu", },
|
||||
{ .name = "clk-rx-icn-hva", },
|
||||
/* This clk needs to be on to keep bus interconnect alive */
|
||||
{ .name = "clk-icn-cpu", .flags = CLK_IS_CRITICAL },
|
||||
/* This clk needs to be on to keep bus interconnect alive */
|
||||
{ .name = "clk-tx-icn-dmu", .flags = CLK_IS_CRITICAL },
|
||||
{ .name = "clk-mmc-0", },
|
||||
{ .name = "clk-mmc-1", },
|
||||
{ .name = "clk-jpegdec", },
|
||||
/* This clk needs to be on to keep A9 running */
|
||||
{ .name = "clk-ext2fa9", .flags = CLK_IS_CRITICAL },
|
||||
{ .name = "clk-ic-bdisp-0", },
|
||||
{ .name = "clk-ic-bdisp-1", },
|
||||
{ .name = "clk-pp-dmu", },
|
||||
{ .name = "clk-vid-dmu", },
|
||||
{ .name = "clk-dss-lpc", },
|
||||
{ .name = "clk-st231-aud-0", },
|
||||
{ .name = "clk-st231-gp-1", },
|
||||
{ .name = "clk-st231-dmu", },
|
||||
/* This clk needs to be on to keep bus interconnect alive */
|
||||
{ .name = "clk-icn-lmi", .flags = CLK_IS_CRITICAL },
|
||||
{ .name = "clk-tx-icn-disp-1", },
|
||||
/* This clk needs to be on to keep bus interconnect alive */
|
||||
{ .name = "clk-icn-sbc", .flags = CLK_IS_CRITICAL },
|
||||
{ .name = "clk-stfe-frc2", },
|
||||
{ .name = "clk-eth-phy", },
|
||||
{ .name = "clk-eth-ref-phyclk", },
|
||||
{ .name = "clk-flash-promip", },
|
||||
{ .name = "clk-main-disp", },
|
||||
{ .name = "clk-aux-disp", },
|
||||
{ .name = "clk-compo-dvp", },
|
||||
{ .name = "clk-tx-icn-hades", },
|
||||
{ .name = "clk-rx-icn-hades", },
|
||||
/* This clk needs to be on to keep bus interconnect alive */
|
||||
{ .name = "clk-icn-reg-16", .flags = CLK_IS_CRITICAL },
|
||||
{ .name = "clk-pp-hades", },
|
||||
{ .name = "clk-clust-hades", },
|
||||
{ .name = "clk-hwpe-hades", },
|
||||
{ .name = "clk-fc-hades", },
|
||||
};
|
||||
|
||||
static const struct clkgen_data clkgen_stih410_c0 = {
|
||||
.outputs = clkgen_stih410_c0_clk_out,
|
||||
.outputs_nb = ARRAY_SIZE(clkgen_stih410_c0_clk_out),
|
||||
};
|
||||
|
||||
static const struct clkgen_clk_out clkgen_stih418_c0_clk_out[] = {
|
||||
{ .name = "clk-icn-gpu", },
|
||||
{ .name = "clk-fdma", },
|
||||
{ .name = "clk-nand", },
|
||||
{ .name = "clk-hva", },
|
||||
{ .name = "clk-proc-stfe", },
|
||||
{ .name = "clk-tp", },
|
||||
/* This clk needs to be on to keep bus interconnect alive */
|
||||
{ .name = "clk-rx-icn-dmu", .flags = CLK_IS_CRITICAL },
|
||||
/* This clk needs to be on to keep bus interconnect alive */
|
||||
{ .name = "clk-rx-icn-hva", .flags = CLK_IS_CRITICAL },
|
||||
{ .name = "clk-icn-cpu", .flags = CLK_IS_CRITICAL },
|
||||
/* This clk needs to be on to keep bus interconnect alive */
|
||||
{ .name = "clk-tx-icn-dmu", .flags = CLK_IS_CRITICAL },
|
||||
{ .name = "clk-mmc-0", },
|
||||
{ .name = "clk-mmc-1", },
|
||||
{ .name = "clk-jpegdec", },
|
||||
/* This clk needs to be on to keep bus interconnect alive */
|
||||
{ .name = "clk-icn-reg", .flags = CLK_IS_CRITICAL },
|
||||
{ .name = "clk-proc-bdisp-0", },
|
||||
{ .name = "clk-proc-bdisp-1", },
|
||||
{ .name = "clk-pp-dmu", },
|
||||
{ .name = "clk-vid-dmu", },
|
||||
{ .name = "clk-dss-lpc", },
|
||||
{ .name = "clk-st231-aud-0", },
|
||||
{ .name = "clk-st231-gp-1", },
|
||||
{ .name = "clk-st231-dmu", },
|
||||
/* This clk needs to be on to keep bus interconnect alive */
|
||||
{ .name = "clk-icn-lmi", .flags = CLK_IS_CRITICAL },
|
||||
/* This clk needs to be on to keep bus interconnect alive */
|
||||
{ .name = "clk-tx-icn-1", .flags = CLK_IS_CRITICAL },
|
||||
/* This clk needs to be on to keep bus interconnect alive */
|
||||
{ .name = "clk-icn-sbc", .flags = CLK_IS_CRITICAL },
|
||||
{ .name = "clk-stfe-frc2", },
|
||||
{ .name = "clk-eth-phyref", },
|
||||
{ .name = "clk-eth-ref-phyclk", },
|
||||
{ .name = "clk-flash-promip", },
|
||||
{ .name = "clk-main-disp", },
|
||||
{ .name = "clk-aux-disp", },
|
||||
{ .name = "clk-compo-dvp", },
|
||||
/* This clk needs to be on to keep bus interconnect alive */
|
||||
{ .name = "clk-tx-icn-hades", .flags = CLK_IS_CRITICAL },
|
||||
/* This clk needs to be on to keep bus interconnect alive */
|
||||
{ .name = "clk-rx-icn-hades", .flags = CLK_IS_CRITICAL },
|
||||
/* This clk needs to be on to keep bus interconnect alive */
|
||||
{ .name = "clk-icn-reg-16", .flags = CLK_IS_CRITICAL },
|
||||
{ .name = "clk-pp-hevc", },
|
||||
{ .name = "clk-clust-hevc", },
|
||||
{ .name = "clk-hwpe-hevc", },
|
||||
{ .name = "clk-fc-hevc", },
|
||||
{ .name = "clk-proc-mixer", },
|
||||
{ .name = "clk-proc-sc", },
|
||||
{ .name = "clk-avsp-hevc", },
|
||||
};
|
||||
|
||||
static const struct clkgen_data clkgen_stih418_c0 = {
|
||||
.outputs = clkgen_stih418_c0_clk_out,
|
||||
.outputs_nb = ARRAY_SIZE(clkgen_stih418_c0_clk_out),
|
||||
};
|
||||
|
||||
static const struct clkgen_clk_out clkgen_stih407_d0_clk_out[] = {
|
||||
{ .name = "clk-pcm-0", },
|
||||
{ .name = "clk-pcm-1", },
|
||||
{ .name = "clk-pcm-2", },
|
||||
{ .name = "clk-spdiff", },
|
||||
};
|
||||
|
||||
static const struct clkgen_data clkgen_stih407_d0 = {
|
||||
.flags = CLK_SET_RATE_PARENT,
|
||||
.outputs = clkgen_stih407_d0_clk_out,
|
||||
.outputs_nb = ARRAY_SIZE(clkgen_stih407_d0_clk_out),
|
||||
};
|
||||
|
||||
static const struct clkgen_clk_out clkgen_stih410_d0_clk_out[] = {
|
||||
{ .name = "clk-pcm-0", },
|
||||
{ .name = "clk-pcm-1", },
|
||||
{ .name = "clk-pcm-2", },
|
||||
{ .name = "clk-spdiff", },
|
||||
{ .name = "clk-pcmr10-master", },
|
||||
{ .name = "clk-usb2-phy", },
|
||||
};
|
||||
|
||||
static const struct clkgen_data clkgen_stih410_d0 = {
|
||||
.flags = CLK_SET_RATE_PARENT,
|
||||
.outputs = clkgen_stih410_d0_clk_out,
|
||||
.outputs_nb = ARRAY_SIZE(clkgen_stih410_d0_clk_out),
|
||||
};
|
||||
|
||||
static const struct clkgen_clk_out clkgen_stih407_d2_clk_out[] = {
|
||||
{ .name = "clk-pix-main-disp", },
|
||||
{ .name = "clk-pix-pip", },
|
||||
{ .name = "clk-pix-gdp1", },
|
||||
{ .name = "clk-pix-gdp2", },
|
||||
{ .name = "clk-pix-gdp3", },
|
||||
{ .name = "clk-pix-gdp4", },
|
||||
{ .name = "clk-pix-aux-disp", },
|
||||
{ .name = "clk-denc", },
|
||||
{ .name = "clk-pix-hddac", },
|
||||
{ .name = "clk-hddac", },
|
||||
{ .name = "clk-sddac", },
|
||||
{ .name = "clk-pix-dvo", },
|
||||
{ .name = "clk-dvo", },
|
||||
{ .name = "clk-pix-hdmi", },
|
||||
{ .name = "clk-tmds-hdmi", },
|
||||
{ .name = "clk-ref-hdmiphy", },
|
||||
};
|
||||
|
||||
static const struct clkgen_data clkgen_stih407_d2 = {
|
||||
.outputs = clkgen_stih407_d2_clk_out,
|
||||
.outputs_nb = ARRAY_SIZE(clkgen_stih407_d2_clk_out),
|
||||
.flags = CLK_SET_RATE_PARENT,
|
||||
.mode = 1,
|
||||
};
|
||||
|
||||
static const struct clkgen_clk_out clkgen_stih418_d2_clk_out[] = {
|
||||
{ .name = "clk-pix-main-disp", },
|
||||
{ .name = "", },
|
||||
{ .name = "", },
|
||||
{ .name = "", },
|
||||
{ .name = "", },
|
||||
{ .name = "clk-tmds-hdmi-div2", },
|
||||
{ .name = "clk-pix-aux-disp", },
|
||||
{ .name = "clk-denc", },
|
||||
{ .name = "clk-pix-hddac", },
|
||||
{ .name = "clk-hddac", },
|
||||
{ .name = "clk-sddac", },
|
||||
{ .name = "clk-pix-dvo", },
|
||||
{ .name = "clk-dvo", },
|
||||
{ .name = "clk-pix-hdmi", },
|
||||
{ .name = "clk-tmds-hdmi", },
|
||||
{ .name = "clk-ref-hdmiphy", },
|
||||
{ .name = "", }, { .name = "", }, { .name = "", }, { .name = "", },
|
||||
{ .name = "", }, { .name = "", }, { .name = "", }, { .name = "", },
|
||||
{ .name = "", }, { .name = "", }, { .name = "", }, { .name = "", },
|
||||
{ .name = "", }, { .name = "", }, { .name = "", }, { .name = "", },
|
||||
{ .name = "", }, { .name = "", }, { .name = "", }, { .name = "", },
|
||||
{ .name = "", }, { .name = "", }, { .name = "", }, { .name = "", },
|
||||
{ .name = "", }, { .name = "", }, { .name = "", }, { .name = "", },
|
||||
{ .name = "", }, { .name = "", }, { .name = "", },
|
||||
{ .name = "clk-vp9", },
|
||||
};
|
||||
|
||||
static const struct clkgen_data clkgen_stih418_d2 = {
|
||||
.outputs = clkgen_stih418_d2_clk_out,
|
||||
.outputs_nb = ARRAY_SIZE(clkgen_stih418_d2_clk_out),
|
||||
.flags = CLK_SET_RATE_PARENT,
|
||||
.mode = 1,
|
||||
};
|
||||
|
||||
static const struct clkgen_clk_out clkgen_stih407_d3_clk_out[] = {
|
||||
{ .name = "clk-stfe-frc1", },
|
||||
{ .name = "clk-tsout-0", },
|
||||
{ .name = "clk-tsout-1", },
|
||||
{ .name = "clk-mchi", },
|
||||
{ .name = "clk-vsens-compo", },
|
||||
{ .name = "clk-frc1-remote", },
|
||||
{ .name = "clk-lpc-0", },
|
||||
{ .name = "clk-lpc-1", },
|
||||
};
|
||||
|
||||
static const struct clkgen_data clkgen_stih407_d3 = {
|
||||
.outputs = clkgen_stih407_d3_clk_out,
|
||||
.outputs_nb = ARRAY_SIZE(clkgen_stih407_d3_clk_out),
|
||||
};
|
||||
|
||||
static const struct of_device_id flexgen_of_match[] = {
|
||||
{
|
||||
.compatible = "st,flexgen-audio",
|
||||
|
@ -304,6 +595,46 @@ static const struct of_device_id flexgen_of_match[] = {
|
|||
.compatible = "st,flexgen-video",
|
||||
.data = &clkgen_video,
|
||||
},
|
||||
{
|
||||
.compatible = "st,flexgen-stih407-a0",
|
||||
.data = &clkgen_stih407_a0,
|
||||
},
|
||||
{
|
||||
.compatible = "st,flexgen-stih410-a0",
|
||||
.data = &clkgen_stih410_a0,
|
||||
},
|
||||
{
|
||||
.compatible = "st,flexgen-stih407-c0",
|
||||
.data = &clkgen_stih407_c0,
|
||||
},
|
||||
{
|
||||
.compatible = "st,flexgen-stih410-c0",
|
||||
.data = &clkgen_stih410_c0,
|
||||
},
|
||||
{
|
||||
.compatible = "st,flexgen-stih418-c0",
|
||||
.data = &clkgen_stih418_c0,
|
||||
},
|
||||
{
|
||||
.compatible = "st,flexgen-stih407-d0",
|
||||
.data = &clkgen_stih407_d0,
|
||||
},
|
||||
{
|
||||
.compatible = "st,flexgen-stih410-d0",
|
||||
.data = &clkgen_stih410_d0,
|
||||
},
|
||||
{
|
||||
.compatible = "st,flexgen-stih407-d2",
|
||||
.data = &clkgen_stih407_d2,
|
||||
},
|
||||
{
|
||||
.compatible = "st,flexgen-stih418-d2",
|
||||
.data = &clkgen_stih418_d2,
|
||||
},
|
||||
{
|
||||
.compatible = "st,flexgen-stih407-d3",
|
||||
.data = &clkgen_stih407_d3,
|
||||
},
|
||||
{}
|
||||
};
|
||||
|
||||
|
@ -320,6 +651,7 @@ static void __init st_of_flexgen_setup(struct device_node *np)
|
|||
unsigned long flex_flags = 0;
|
||||
int ret;
|
||||
bool clk_mode = 0;
|
||||
const char *clk_name;
|
||||
|
||||
pnode = of_get_parent(np);
|
||||
if (!pnode)
|
||||
|
@ -347,13 +679,17 @@ static void __init st_of_flexgen_setup(struct device_node *np)
|
|||
if (!clk_data)
|
||||
goto err;
|
||||
|
||||
ret = of_property_count_strings(np, "clock-output-names");
|
||||
if (ret <= 0) {
|
||||
pr_err("%s: Failed to get number of output clocks (%d)",
|
||||
__func__, clk_data->clk_num);
|
||||
goto err;
|
||||
}
|
||||
clk_data->clk_num = ret;
|
||||
/* First try to get output information from the compatible data */
|
||||
if (!data || !data->outputs_nb || !data->outputs) {
|
||||
ret = of_property_count_strings(np, "clock-output-names");
|
||||
if (ret <= 0) {
|
||||
pr_err("%s: Failed to get number of output clocks (%d)",
|
||||
__func__, clk_data->clk_num);
|
||||
goto err;
|
||||
}
|
||||
clk_data->clk_num = ret;
|
||||
} else
|
||||
clk_data->clk_num = data->outputs_nb;
|
||||
|
||||
clk_data->clks = kcalloc(clk_data->clk_num, sizeof(struct clk *),
|
||||
GFP_KERNEL);
|
||||
|
@ -368,16 +704,19 @@ static void __init st_of_flexgen_setup(struct device_node *np)
|
|||
|
||||
for (i = 0; i < clk_data->clk_num; i++) {
|
||||
struct clk *clk;
|
||||
const char *clk_name;
|
||||
|
||||
if (of_property_read_string_index(np, "clock-output-names",
|
||||
i, &clk_name)) {
|
||||
break;
|
||||
if (!data || !data->outputs_nb || !data->outputs) {
|
||||
if (of_property_read_string_index(np,
|
||||
"clock-output-names",
|
||||
i, &clk_name))
|
||||
break;
|
||||
flex_flags &= ~CLK_IS_CRITICAL;
|
||||
of_clk_detect_critical(np, i, &flex_flags);
|
||||
} else {
|
||||
clk_name = data->outputs[i].name;
|
||||
flex_flags = data->flags | data->outputs[i].flags;
|
||||
}
|
||||
|
||||
flex_flags &= ~CLK_IS_CRITICAL;
|
||||
of_clk_detect_critical(np, i, &flex_flags);
|
||||
|
||||
/*
|
||||
* If we read an empty clock name then the output is unused
|
||||
*/
|
||||
|
|
|
@ -66,6 +66,16 @@ struct clkgen_quadfs_data {
|
|||
unsigned long *);
|
||||
};
|
||||
|
||||
struct clkgen_clk_out {
|
||||
const char *name;
|
||||
unsigned long flags;
|
||||
};
|
||||
|
||||
struct clkgen_quadfs_data_clks {
|
||||
struct clkgen_quadfs_data *data;
|
||||
const struct clkgen_clk_out *outputs;
|
||||
};
|
||||
|
||||
static const struct clk_ops st_quadfs_pll_c32_ops;
|
||||
|
||||
static int clk_fs660c32_dig_get_params(unsigned long input,
|
||||
|
@ -115,6 +125,18 @@ static const struct clkgen_quadfs_data st_fs660c32_C = {
|
|||
.get_rate = clk_fs660c32_dig_get_rate,
|
||||
};
|
||||
|
||||
static const struct clkgen_clk_out st_fs660c32_C_clks[] = {
|
||||
{ .name = "clk-s-c0-fs0-ch0", },
|
||||
{ .name = "clk-s-c0-fs0-ch1", },
|
||||
{ .name = "clk-s-c0-fs0-ch2", },
|
||||
{ .name = "clk-s-c0-fs0-ch3", },
|
||||
};
|
||||
|
||||
static const struct clkgen_quadfs_data_clks st_fs660c32_C_data = {
|
||||
.data = (struct clkgen_quadfs_data *)&st_fs660c32_C,
|
||||
.outputs = st_fs660c32_C_clks,
|
||||
};
|
||||
|
||||
static const struct clkgen_quadfs_data st_fs660c32_D = {
|
||||
.nrst_present = true,
|
||||
.nrst = { CLKGEN_FIELD(0x2a0, 0x1, 0),
|
||||
|
@ -156,6 +178,46 @@ static const struct clkgen_quadfs_data st_fs660c32_D = {
|
|||
.get_params = clk_fs660c32_dig_get_params,
|
||||
.get_rate = clk_fs660c32_dig_get_rate,};
|
||||
|
||||
static const struct clkgen_quadfs_data_clks st_fs660c32_D_data = {
|
||||
.data = (struct clkgen_quadfs_data *)&st_fs660c32_D,
|
||||
};
|
||||
|
||||
static const struct clkgen_clk_out st_fs660c32_D0_clks[] = {
|
||||
{ .name = "clk-s-d0-fs0-ch0", },
|
||||
{ .name = "clk-s-d0-fs0-ch1", },
|
||||
{ .name = "clk-s-d0-fs0-ch2", },
|
||||
{ .name = "clk-s-d0-fs0-ch3", },
|
||||
};
|
||||
|
||||
static const struct clkgen_quadfs_data_clks st_fs660c32_D0_data = {
|
||||
.data = (struct clkgen_quadfs_data *)&st_fs660c32_D,
|
||||
.outputs = st_fs660c32_D0_clks,
|
||||
};
|
||||
|
||||
static const struct clkgen_clk_out st_fs660c32_D2_clks[] = {
|
||||
{ .name = "clk-s-d2-fs0-ch0", },
|
||||
{ .name = "clk-s-d2-fs0-ch1", },
|
||||
{ .name = "clk-s-d2-fs0-ch2", },
|
||||
{ .name = "clk-s-d2-fs0-ch3", },
|
||||
};
|
||||
|
||||
static const struct clkgen_quadfs_data_clks st_fs660c32_D2_data = {
|
||||
.data = (struct clkgen_quadfs_data *)&st_fs660c32_D,
|
||||
.outputs = st_fs660c32_D2_clks,
|
||||
};
|
||||
|
||||
static const struct clkgen_clk_out st_fs660c32_D3_clks[] = {
|
||||
{ .name = "clk-s-d3-fs0-ch0", },
|
||||
{ .name = "clk-s-d3-fs0-ch1", },
|
||||
{ .name = "clk-s-d3-fs0-ch2", },
|
||||
{ .name = "clk-s-d3-fs0-ch3", },
|
||||
};
|
||||
|
||||
static const struct clkgen_quadfs_data_clks st_fs660c32_D3_data = {
|
||||
.data = (struct clkgen_quadfs_data *)&st_fs660c32_D,
|
||||
.outputs = st_fs660c32_D3_clks,
|
||||
};
|
||||
|
||||
/**
|
||||
* DOC: A Frequency Synthesizer that multiples its input clock by a fixed factor
|
||||
*
|
||||
|
@ -857,7 +919,7 @@ static struct clk * __init st_clk_register_quadfs_fsynth(
|
|||
|
||||
static void __init st_of_create_quadfs_fsynths(
|
||||
struct device_node *np, const char *pll_name,
|
||||
struct clkgen_quadfs_data *quadfs, void __iomem *reg,
|
||||
struct clkgen_quadfs_data_clks *quadfs, void __iomem *reg,
|
||||
spinlock_t *lock)
|
||||
{
|
||||
struct clk_onecell_data *clk_data;
|
||||
|
@ -881,9 +943,15 @@ static void __init st_of_create_quadfs_fsynths(
|
|||
const char *clk_name;
|
||||
unsigned long flags = 0;
|
||||
|
||||
if (of_property_read_string_index(np, "clock-output-names",
|
||||
fschan, &clk_name)) {
|
||||
break;
|
||||
if (quadfs->outputs) {
|
||||
clk_name = quadfs->outputs[fschan].name;
|
||||
flags = quadfs->outputs[fschan].flags;
|
||||
} else {
|
||||
if (of_property_read_string_index(np,
|
||||
"clock-output-names",
|
||||
fschan, &clk_name))
|
||||
break;
|
||||
of_clk_detect_critical(np, fschan, &flags);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -892,10 +960,8 @@ static void __init st_of_create_quadfs_fsynths(
|
|||
if (*clk_name == '\0')
|
||||
continue;
|
||||
|
||||
of_clk_detect_critical(np, fschan, &flags);
|
||||
|
||||
clk = st_clk_register_quadfs_fsynth(clk_name, pll_name,
|
||||
quadfs, reg, fschan,
|
||||
quadfs->data, reg, fschan,
|
||||
flags, lock);
|
||||
|
||||
/*
|
||||
|
@ -915,7 +981,7 @@ static void __init st_of_create_quadfs_fsynths(
|
|||
}
|
||||
|
||||
static void __init st_of_quadfs_setup(struct device_node *np,
|
||||
struct clkgen_quadfs_data *data)
|
||||
struct clkgen_quadfs_data_clks *datac)
|
||||
{
|
||||
struct clk *clk;
|
||||
const char *pll_name, *clk_parent_name;
|
||||
|
@ -940,7 +1006,7 @@ static void __init st_of_quadfs_setup(struct device_node *np,
|
|||
|
||||
spin_lock_init(lock);
|
||||
|
||||
clk = st_clk_register_quadfs_pll(pll_name, clk_parent_name, data,
|
||||
clk = st_clk_register_quadfs_pll(pll_name, clk_parent_name, datac->data,
|
||||
reg, lock);
|
||||
if (IS_ERR(clk))
|
||||
goto err_exit;
|
||||
|
@ -950,7 +1016,7 @@ static void __init st_of_quadfs_setup(struct device_node *np,
|
|||
__clk_get_name(clk_get_parent(clk)),
|
||||
(unsigned int)clk_get_rate(clk));
|
||||
|
||||
st_of_create_quadfs_fsynths(np, pll_name, data, reg, lock);
|
||||
st_of_create_quadfs_fsynths(np, pll_name, datac, reg, lock);
|
||||
|
||||
err_exit:
|
||||
kfree(pll_name); /* No longer need local copy of the PLL name */
|
||||
|
@ -958,12 +1024,35 @@ err_exit:
|
|||
|
||||
static void __init st_of_quadfs660C_setup(struct device_node *np)
|
||||
{
|
||||
st_of_quadfs_setup(np, (struct clkgen_quadfs_data *) &st_fs660c32_C);
|
||||
st_of_quadfs_setup(np,
|
||||
(struct clkgen_quadfs_data_clks *) &st_fs660c32_C_data);
|
||||
}
|
||||
CLK_OF_DECLARE(quadfs660C, "st,quadfs-pll", st_of_quadfs660C_setup);
|
||||
|
||||
static void __init st_of_quadfs660D_setup(struct device_node *np)
|
||||
{
|
||||
st_of_quadfs_setup(np, (struct clkgen_quadfs_data *) &st_fs660c32_D);
|
||||
st_of_quadfs_setup(np,
|
||||
(struct clkgen_quadfs_data_clks *) &st_fs660c32_D_data);
|
||||
}
|
||||
CLK_OF_DECLARE(quadfs660D, "st,quadfs", st_of_quadfs660D_setup);
|
||||
|
||||
static void __init st_of_quadfs660D0_setup(struct device_node *np)
|
||||
{
|
||||
st_of_quadfs_setup(np,
|
||||
(struct clkgen_quadfs_data_clks *) &st_fs660c32_D0_data);
|
||||
}
|
||||
CLK_OF_DECLARE(quadfs660D0, "st,quadfs-d0", st_of_quadfs660D0_setup);
|
||||
|
||||
static void __init st_of_quadfs660D2_setup(struct device_node *np)
|
||||
{
|
||||
st_of_quadfs_setup(np,
|
||||
(struct clkgen_quadfs_data_clks *) &st_fs660c32_D2_data);
|
||||
}
|
||||
CLK_OF_DECLARE(quadfs660D2, "st,quadfs-d2", st_of_quadfs660D2_setup);
|
||||
|
||||
static void __init st_of_quadfs660D3_setup(struct device_node *np)
|
||||
{
|
||||
st_of_quadfs_setup(np,
|
||||
(struct clkgen_quadfs_data_clks *) &st_fs660c32_D3_data);
|
||||
}
|
||||
CLK_OF_DECLARE(quadfs660D3, "st,quadfs-d3", st_of_quadfs660D3_setup);
|
||||
|
|
|
@ -57,6 +57,17 @@ struct clkgen_pll_data {
|
|||
const struct clk_ops *ops;
|
||||
};
|
||||
|
||||
struct clkgen_clk_out {
|
||||
const char *name;
|
||||
unsigned long flags;
|
||||
};
|
||||
|
||||
struct clkgen_pll_data_clks {
|
||||
struct clkgen_pll_data *data;
|
||||
const struct clkgen_clk_out *outputs;
|
||||
};
|
||||
|
||||
|
||||
static const struct clk_ops stm_pll3200c32_ops;
|
||||
static const struct clk_ops stm_pll3200c32_a9_ops;
|
||||
static const struct clk_ops stm_pll4600c28_ops;
|
||||
|
@ -74,6 +85,28 @@ static const struct clkgen_pll_data st_pll3200c32_cx_0 = {
|
|||
.ops = &stm_pll3200c32_ops,
|
||||
};
|
||||
|
||||
static const struct clkgen_pll_data_clks st_pll3200c32_cx_0_legacy_data = {
|
||||
.data = (struct clkgen_pll_data *)&st_pll3200c32_cx_0,
|
||||
};
|
||||
|
||||
static const struct clkgen_clk_out st_pll3200c32_ax_0_clks[] = {
|
||||
{ .name = "clk-s-a0-pll-odf-0", },
|
||||
};
|
||||
|
||||
static const struct clkgen_pll_data_clks st_pll3200c32_a0_data = {
|
||||
.data = (struct clkgen_pll_data *)&st_pll3200c32_cx_0,
|
||||
.outputs = st_pll3200c32_ax_0_clks,
|
||||
};
|
||||
|
||||
static const struct clkgen_clk_out st_pll3200c32_cx_0_clks[] = {
|
||||
{ .name = "clk-s-c0-pll0-odf-0", },
|
||||
};
|
||||
|
||||
static const struct clkgen_pll_data_clks st_pll3200c32_c0_data = {
|
||||
.data = (struct clkgen_pll_data *)&st_pll3200c32_cx_0,
|
||||
.outputs = st_pll3200c32_cx_0_clks,
|
||||
};
|
||||
|
||||
static const struct clkgen_pll_data st_pll3200c32_cx_1 = {
|
||||
/* 407 C0 PLL1 */
|
||||
.pdn_status = CLKGEN_FIELD(0x2c8, 0x1, 8),
|
||||
|
@ -87,6 +120,19 @@ static const struct clkgen_pll_data st_pll3200c32_cx_1 = {
|
|||
.ops = &stm_pll3200c32_ops,
|
||||
};
|
||||
|
||||
static const struct clkgen_pll_data_clks st_pll3200c32_cx_1_legacy_data = {
|
||||
.data = (struct clkgen_pll_data *)&st_pll3200c32_cx_1,
|
||||
};
|
||||
|
||||
static const struct clkgen_clk_out st_pll3200c32_cx_1_clks[] = {
|
||||
{ .name = "clk-s-c0-pll1-odf-0", },
|
||||
};
|
||||
|
||||
static const struct clkgen_pll_data_clks st_pll3200c32_c1_data = {
|
||||
.data = (struct clkgen_pll_data *)&st_pll3200c32_cx_1,
|
||||
.outputs = st_pll3200c32_cx_1_clks,
|
||||
};
|
||||
|
||||
static const struct clkgen_pll_data st_pll3200c32_407_a9 = {
|
||||
/* 407 A9 */
|
||||
.pdn_status = CLKGEN_FIELD(0x1a8, 0x1, 0),
|
||||
|
@ -104,6 +150,15 @@ static const struct clkgen_pll_data st_pll3200c32_407_a9 = {
|
|||
.ops = &stm_pll3200c32_a9_ops,
|
||||
};
|
||||
|
||||
static const struct clkgen_clk_out st_pll3200c32_407_a9_clks[] = {
|
||||
{ .name = "clockgen-a9-pll-odf", },
|
||||
};
|
||||
|
||||
static const struct clkgen_pll_data_clks st_pll3200c32_407_a9_data = {
|
||||
.data = (struct clkgen_pll_data *)&st_pll3200c32_407_a9,
|
||||
.outputs = st_pll3200c32_407_a9_clks,
|
||||
};
|
||||
|
||||
static struct clkgen_pll_data st_pll4600c28_418_a9 = {
|
||||
/* 418 A9 */
|
||||
.pdn_status = CLKGEN_FIELD(0x1a8, 0x1, 0),
|
||||
|
@ -120,6 +175,15 @@ static struct clkgen_pll_data st_pll4600c28_418_a9 = {
|
|||
.ops = &stm_pll4600c28_ops,
|
||||
};
|
||||
|
||||
static const struct clkgen_clk_out st_pll4600c28_418_a9_clks[] = {
|
||||
{ .name = "clockgen-a9-pll-odf", },
|
||||
};
|
||||
|
||||
static const struct clkgen_pll_data_clks st_pll4600c28_418_a9_data = {
|
||||
.data = (struct clkgen_pll_data *)&st_pll4600c28_418_a9,
|
||||
.outputs = st_pll4600c28_418_a9_clks,
|
||||
};
|
||||
|
||||
/**
|
||||
* DOC: Clock Generated by PLL, rate set and enabled by bootloader
|
||||
*
|
||||
|
@ -146,7 +210,6 @@ struct clkgen_pll {
|
|||
|
||||
u32 ndiv;
|
||||
u32 idf;
|
||||
u32 odf;
|
||||
u32 cp;
|
||||
};
|
||||
|
||||
|
@ -685,7 +748,7 @@ static struct clk * __init clkgen_odf_register(const char *parent_name,
|
|||
|
||||
|
||||
static void __init clkgen_c32_pll_setup(struct device_node *np,
|
||||
struct clkgen_pll_data *data)
|
||||
struct clkgen_pll_data_clks *datac)
|
||||
{
|
||||
struct clk *clk;
|
||||
const char *parent_name, *pll_name;
|
||||
|
@ -705,14 +768,14 @@ static void __init clkgen_c32_pll_setup(struct device_node *np,
|
|||
|
||||
of_clk_detect_critical(np, 0, &pll_flags);
|
||||
|
||||
clk = clkgen_pll_register(parent_name, data, pll_base, pll_flags,
|
||||
np->name, data->lock);
|
||||
clk = clkgen_pll_register(parent_name, datac->data, pll_base, pll_flags,
|
||||
np->name, datac->data->lock);
|
||||
if (IS_ERR(clk))
|
||||
return;
|
||||
|
||||
pll_name = __clk_get_name(clk);
|
||||
|
||||
num_odfs = data->num_odfs;
|
||||
num_odfs = datac->data->num_odfs;
|
||||
|
||||
clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
|
||||
if (!clk_data)
|
||||
|
@ -730,14 +793,21 @@ static void __init clkgen_c32_pll_setup(struct device_node *np,
|
|||
const char *clk_name;
|
||||
unsigned long odf_flags = 0;
|
||||
|
||||
if (of_property_read_string_index(np, "clock-output-names",
|
||||
odf, &clk_name))
|
||||
return;
|
||||
if (datac->outputs) {
|
||||
clk_name = datac->outputs[odf].name;
|
||||
odf_flags = datac->outputs[odf].flags;
|
||||
} else {
|
||||
if (of_property_read_string_index(np,
|
||||
"clock-output-names",
|
||||
odf, &clk_name))
|
||||
return;
|
||||
|
||||
of_clk_detect_critical(np, odf, &odf_flags);
|
||||
of_clk_detect_critical(np, odf, &odf_flags);
|
||||
}
|
||||
|
||||
clk = clkgen_odf_register(pll_name, pll_base, data, odf_flags,
|
||||
odf, &clkgena_c32_odf_lock, clk_name);
|
||||
clk = clkgen_odf_register(pll_name, pll_base, datac->data,
|
||||
odf_flags, odf, &clkgena_c32_odf_lock,
|
||||
clk_name);
|
||||
if (IS_ERR(clk))
|
||||
goto err;
|
||||
|
||||
|
@ -755,27 +825,48 @@ err:
|
|||
static void __init clkgen_c32_pll0_setup(struct device_node *np)
|
||||
{
|
||||
clkgen_c32_pll_setup(np,
|
||||
(struct clkgen_pll_data *) &st_pll3200c32_cx_0);
|
||||
(struct clkgen_pll_data_clks *) &st_pll3200c32_cx_0_legacy_data);
|
||||
}
|
||||
CLK_OF_DECLARE(c32_pll0, "st,clkgen-pll0", clkgen_c32_pll0_setup);
|
||||
|
||||
static void __init clkgen_c32_pll0_a0_setup(struct device_node *np)
|
||||
{
|
||||
clkgen_c32_pll_setup(np,
|
||||
(struct clkgen_pll_data_clks *) &st_pll3200c32_a0_data);
|
||||
}
|
||||
CLK_OF_DECLARE(c32_pll0_a0, "st,clkgen-pll0-a0", clkgen_c32_pll0_a0_setup);
|
||||
|
||||
static void __init clkgen_c32_pll0_c0_setup(struct device_node *np)
|
||||
{
|
||||
clkgen_c32_pll_setup(np,
|
||||
(struct clkgen_pll_data_clks *) &st_pll3200c32_c0_data);
|
||||
}
|
||||
CLK_OF_DECLARE(c32_pll0_c0, "st,clkgen-pll0-c0", clkgen_c32_pll0_c0_setup);
|
||||
|
||||
static void __init clkgen_c32_pll1_setup(struct device_node *np)
|
||||
{
|
||||
clkgen_c32_pll_setup(np,
|
||||
(struct clkgen_pll_data *) &st_pll3200c32_cx_1);
|
||||
(struct clkgen_pll_data_clks *) &st_pll3200c32_cx_1_legacy_data);
|
||||
}
|
||||
CLK_OF_DECLARE(c32_pll1, "st,clkgen-pll1", clkgen_c32_pll1_setup);
|
||||
|
||||
static void __init clkgen_c32_pll1_c0_setup(struct device_node *np)
|
||||
{
|
||||
clkgen_c32_pll_setup(np,
|
||||
(struct clkgen_pll_data_clks *) &st_pll3200c32_c1_data);
|
||||
}
|
||||
CLK_OF_DECLARE(c32_pll1_c0, "st,clkgen-pll1-c0", clkgen_c32_pll1_c0_setup);
|
||||
|
||||
static void __init clkgen_c32_plla9_setup(struct device_node *np)
|
||||
{
|
||||
clkgen_c32_pll_setup(np,
|
||||
(struct clkgen_pll_data *) &st_pll3200c32_407_a9);
|
||||
(struct clkgen_pll_data_clks *) &st_pll3200c32_407_a9_data);
|
||||
}
|
||||
CLK_OF_DECLARE(c32_plla9, "st,stih407-clkgen-plla9", clkgen_c32_plla9_setup);
|
||||
|
||||
static void __init clkgen_c28_plla9_setup(struct device_node *np)
|
||||
{
|
||||
clkgen_c32_pll_setup(np,
|
||||
(struct clkgen_pll_data *) &st_pll4600c28_418_a9);
|
||||
(struct clkgen_pll_data_clks *) &st_pll4600c28_418_a9_data);
|
||||
}
|
||||
CLK_OF_DECLARE(c28_plla9, "st,stih418-clkgen-plla9", clkgen_c28_plla9_setup);
|
||||
|
|
|
@ -0,0 +1,165 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later or BSD-2-Clause */
|
||||
/*
|
||||
* Copyright (c) 2019-2020, Huawei Tech. Co., Ltd.
|
||||
*
|
||||
* Author: Dongjiu Geng <gengdongjiu@huawei.com>
|
||||
*/
|
||||
|
||||
#ifndef __DTS_HI3559AV100_CLOCK_H
|
||||
#define __DTS_HI3559AV100_CLOCK_H
|
||||
|
||||
/* fixed rate */
|
||||
#define HI3559AV100_FIXED_1188M 1
|
||||
#define HI3559AV100_FIXED_1000M 2
|
||||
#define HI3559AV100_FIXED_842M 3
|
||||
#define HI3559AV100_FIXED_792M 4
|
||||
#define HI3559AV100_FIXED_750M 5
|
||||
#define HI3559AV100_FIXED_710M 6
|
||||
#define HI3559AV100_FIXED_680M 7
|
||||
#define HI3559AV100_FIXED_667M 8
|
||||
#define HI3559AV100_FIXED_631M 9
|
||||
#define HI3559AV100_FIXED_600M 10
|
||||
#define HI3559AV100_FIXED_568M 11
|
||||
#define HI3559AV100_FIXED_500M 12
|
||||
#define HI3559AV100_FIXED_475M 13
|
||||
#define HI3559AV100_FIXED_428M 14
|
||||
#define HI3559AV100_FIXED_400M 15
|
||||
#define HI3559AV100_FIXED_396M 16
|
||||
#define HI3559AV100_FIXED_300M 17
|
||||
#define HI3559AV100_FIXED_250M 18
|
||||
#define HI3559AV100_FIXED_198M 19
|
||||
#define HI3559AV100_FIXED_187p5M 20
|
||||
#define HI3559AV100_FIXED_150M 21
|
||||
#define HI3559AV100_FIXED_148p5M 22
|
||||
#define HI3559AV100_FIXED_125M 23
|
||||
#define HI3559AV100_FIXED_107M 24
|
||||
#define HI3559AV100_FIXED_100M 25
|
||||
#define HI3559AV100_FIXED_99M 26
|
||||
#define HI3559AV100_FIXED_74p25M 27
|
||||
#define HI3559AV100_FIXED_72M 28
|
||||
#define HI3559AV100_FIXED_60M 29
|
||||
#define HI3559AV100_FIXED_54M 30
|
||||
#define HI3559AV100_FIXED_50M 31
|
||||
#define HI3559AV100_FIXED_49p5M 32
|
||||
#define HI3559AV100_FIXED_37p125M 33
|
||||
#define HI3559AV100_FIXED_36M 34
|
||||
#define HI3559AV100_FIXED_32p4M 35
|
||||
#define HI3559AV100_FIXED_27M 36
|
||||
#define HI3559AV100_FIXED_25M 37
|
||||
#define HI3559AV100_FIXED_24M 38
|
||||
#define HI3559AV100_FIXED_12M 39
|
||||
#define HI3559AV100_FIXED_3M 40
|
||||
#define HI3559AV100_FIXED_1p6M 41
|
||||
#define HI3559AV100_FIXED_400K 42
|
||||
#define HI3559AV100_FIXED_100K 43
|
||||
#define HI3559AV100_FIXED_200M 44
|
||||
#define HI3559AV100_FIXED_75M 75
|
||||
|
||||
#define HI3559AV100_I2C0_CLK 50
|
||||
#define HI3559AV100_I2C1_CLK 51
|
||||
#define HI3559AV100_I2C2_CLK 52
|
||||
#define HI3559AV100_I2C3_CLK 53
|
||||
#define HI3559AV100_I2C4_CLK 54
|
||||
#define HI3559AV100_I2C5_CLK 55
|
||||
#define HI3559AV100_I2C6_CLK 56
|
||||
#define HI3559AV100_I2C7_CLK 57
|
||||
#define HI3559AV100_I2C8_CLK 58
|
||||
#define HI3559AV100_I2C9_CLK 59
|
||||
#define HI3559AV100_I2C10_CLK 60
|
||||
#define HI3559AV100_I2C11_CLK 61
|
||||
|
||||
#define HI3559AV100_SPI0_CLK 62
|
||||
#define HI3559AV100_SPI1_CLK 63
|
||||
#define HI3559AV100_SPI2_CLK 64
|
||||
#define HI3559AV100_SPI3_CLK 65
|
||||
#define HI3559AV100_SPI4_CLK 66
|
||||
#define HI3559AV100_SPI5_CLK 67
|
||||
#define HI3559AV100_SPI6_CLK 68
|
||||
|
||||
#define HI3559AV100_EDMAC_CLK 69
|
||||
#define HI3559AV100_EDMAC_AXICLK 70
|
||||
#define HI3559AV100_EDMAC1_CLK 71
|
||||
#define HI3559AV100_EDMAC1_AXICLK 72
|
||||
#define HI3559AV100_VDMAC_CLK 73
|
||||
|
||||
/* mux clocks */
|
||||
#define HI3559AV100_FMC_MUX 80
|
||||
#define HI3559AV100_SYSAPB_MUX 81
|
||||
#define HI3559AV100_UART_MUX 82
|
||||
#define HI3559AV100_SYSBUS_MUX 83
|
||||
#define HI3559AV100_A73_MUX 84
|
||||
#define HI3559AV100_MMC0_MUX 85
|
||||
#define HI3559AV100_MMC1_MUX 86
|
||||
#define HI3559AV100_MMC2_MUX 87
|
||||
#define HI3559AV100_MMC3_MUX 88
|
||||
|
||||
/* gate clocks */
|
||||
#define HI3559AV100_FMC_CLK 90
|
||||
#define HI3559AV100_UART0_CLK 91
|
||||
#define HI3559AV100_UART1_CLK 92
|
||||
#define HI3559AV100_UART2_CLK 93
|
||||
#define HI3559AV100_UART3_CLK 94
|
||||
#define HI3559AV100_UART4_CLK 95
|
||||
#define HI3559AV100_MMC0_CLK 96
|
||||
#define HI3559AV100_MMC1_CLK 97
|
||||
#define HI3559AV100_MMC2_CLK 98
|
||||
#define HI3559AV100_MMC3_CLK 99
|
||||
|
||||
#define HI3559AV100_ETH_CLK 100
|
||||
#define HI3559AV100_ETH_MACIF_CLK 101
|
||||
#define HI3559AV100_ETH1_CLK 102
|
||||
#define HI3559AV100_ETH1_MACIF_CLK 103
|
||||
|
||||
/* complex */
|
||||
#define HI3559AV100_MAC0_CLK 110
|
||||
#define HI3559AV100_MAC1_CLK 111
|
||||
#define HI3559AV100_SATA_CLK 112
|
||||
#define HI3559AV100_USB_CLK 113
|
||||
#define HI3559AV100_USB1_CLK 114
|
||||
|
||||
/* pll clocks */
|
||||
#define HI3559AV100_APLL_CLK 250
|
||||
#define HI3559AV100_GPLL_CLK 251
|
||||
|
||||
#define HI3559AV100_CRG_NR_CLKS 256
|
||||
|
||||
#define HI3559AV100_SHUB_SOURCE_SOC_24M 0
|
||||
#define HI3559AV100_SHUB_SOURCE_SOC_200M 1
|
||||
#define HI3559AV100_SHUB_SOURCE_SOC_300M 2
|
||||
#define HI3559AV100_SHUB_SOURCE_PLL 3
|
||||
#define HI3559AV100_SHUB_SOURCE_CLK 4
|
||||
|
||||
#define HI3559AV100_SHUB_I2C0_CLK 10
|
||||
#define HI3559AV100_SHUB_I2C1_CLK 11
|
||||
#define HI3559AV100_SHUB_I2C2_CLK 12
|
||||
#define HI3559AV100_SHUB_I2C3_CLK 13
|
||||
#define HI3559AV100_SHUB_I2C4_CLK 14
|
||||
#define HI3559AV100_SHUB_I2C5_CLK 15
|
||||
#define HI3559AV100_SHUB_I2C6_CLK 16
|
||||
#define HI3559AV100_SHUB_I2C7_CLK 17
|
||||
|
||||
#define HI3559AV100_SHUB_SPI_SOURCE_CLK 20
|
||||
#define HI3559AV100_SHUB_SPI4_SOURCE_CLK 21
|
||||
#define HI3559AV100_SHUB_SPI0_CLK 22
|
||||
#define HI3559AV100_SHUB_SPI1_CLK 23
|
||||
#define HI3559AV100_SHUB_SPI2_CLK 24
|
||||
#define HI3559AV100_SHUB_SPI3_CLK 25
|
||||
#define HI3559AV100_SHUB_SPI4_CLK 26
|
||||
|
||||
#define HI3559AV100_SHUB_UART_CLK_32K 30
|
||||
#define HI3559AV100_SHUB_UART_SOURCE_CLK 31
|
||||
#define HI3559AV100_SHUB_UART_DIV_CLK 32
|
||||
#define HI3559AV100_SHUB_UART0_CLK 33
|
||||
#define HI3559AV100_SHUB_UART1_CLK 34
|
||||
#define HI3559AV100_SHUB_UART2_CLK 35
|
||||
#define HI3559AV100_SHUB_UART3_CLK 36
|
||||
#define HI3559AV100_SHUB_UART4_CLK 37
|
||||
#define HI3559AV100_SHUB_UART5_CLK 38
|
||||
#define HI3559AV100_SHUB_UART6_CLK 39
|
||||
|
||||
#define HI3559AV100_SHUB_EDMAC_CLK 40
|
||||
|
||||
#define HI3559AV100_SHUB_NR_CLKS 50
|
||||
|
||||
#endif /* __DTS_HI3559AV100_CLOCK_H */
|
||||
|
Loading…
Reference in New Issue