Merge branches 'clk-x86', 'clk-stm', 'clk-amlogic' and 'clk-allwinner' into clk-next

* clk-x86:
  clk: x86: Fix clk_gate_flags for RV_CLK_GATE
  clk: x86: Use dynamic con_id string during clk registration
  ACPI: APD: Add a fmw property clk-name
  drivers: acpi: acpi_apd: Remove unused device property "is-rv"
  x86: clk: clk-fch: Add support for newer family of AMD's SOC
  clk: Introduce clk-tps68470 driver
  platform/x86: int3472: Deal with probe ordering issues
  platform/x86: int3472: Pass tps68470_regulator_platform_data to the tps68470-regulator MFD-cell
  platform/x86: int3472: Pass tps68470_clk_platform_data to the tps68470-regulator MFD-cell
  platform/x86: int3472: Add get_sensor_adev_and_name() helper
  platform/x86: int3472: Split into 2 drivers
  platform_data: Add linux/platform_data/tps68470.h file
  i2c: acpi: Add i2c_acpi_new_device_by_fwnode() function
  i2c: acpi: Use acpi_dev_ready_for_enumeration() helper
  ACPI: delay enumeration of devices with a _DEP pointing to an INT3472 device

* clk-stm:
  clk: stm32: Fix ltdc's clock turn off by clk_disable_unused() after system enter shell

* clk-amlogic:
  clk: meson: gxbb: Fix the SDM_EN bit for MPLL0 on GXBB

* clk-allwinner:
  clk: sunxi-ng: Add support for the D1 SoC clocks
  clk: sunxi-ng: gate: Add macros for gates with fixed dividers
  clk: sunxi-ng: mux: Add macros using clk_parent_data and clk_hw
  clk: sunxi-ng: mp: Add macros using clk_parent_data and clk_hw
  clk: sunxi-ng: div: Add macros using clk_parent_data and clk_hw
  dt-bindings: clk: Add compatibles for D1 CCUs
  clk: sunxi-ng: Allow the CCU core to be built as a module
  clk: sunxi-ng: Convert early providers to platform drivers
  clk: sunxi-ng: Allow drivers to be built as modules
  clk: sunxi-ng: Export symbols used by CCU drivers
This commit is contained in:
Stephen Boyd 2022-01-11 18:30:35 -08:00
74 changed files with 3369 additions and 438 deletions

View File

@ -34,6 +34,8 @@ properties:
- allwinner,sun8i-v3-ccu - allwinner,sun8i-v3-ccu
- allwinner,sun8i-v3s-ccu - allwinner,sun8i-v3s-ccu
- allwinner,sun9i-a80-ccu - allwinner,sun9i-a80-ccu
- allwinner,sun20i-d1-ccu
- allwinner,sun20i-d1-r-ccu
- allwinner,sun50i-a64-ccu - allwinner,sun50i-a64-ccu
- allwinner,sun50i-a64-r-ccu - allwinner,sun50i-a64-r-ccu
- allwinner,sun50i-a100-ccu - allwinner,sun50i-a100-ccu
@ -79,6 +81,7 @@ if:
enum: enum:
- allwinner,sun8i-a83t-r-ccu - allwinner,sun8i-a83t-r-ccu
- allwinner,sun8i-h3-r-ccu - allwinner,sun8i-h3-r-ccu
- allwinner,sun20i-d1-r-ccu
- allwinner,sun50i-a64-r-ccu - allwinner,sun50i-a64-r-ccu
- allwinner,sun50i-a100-r-ccu - allwinner,sun50i-a100-r-ccu
- allwinner,sun50i-h6-r-ccu - allwinner,sun50i-h6-r-ccu
@ -99,6 +102,7 @@ else:
properties: properties:
compatible: compatible:
enum: enum:
- allwinner,sun20i-d1-ccu
- allwinner,sun50i-a100-ccu - allwinner,sun50i-a100-ccu
- allwinner,sun50i-h6-ccu - allwinner,sun50i-h6-ccu
- allwinner,sun50i-h616-ccu - allwinner,sun50i-h616-ccu

View File

@ -87,8 +87,15 @@ static int fch_misc_setup(struct apd_private_data *pdata)
if (ret < 0) if (ret < 0)
return -ENOENT; return -ENOENT;
if (!acpi_dev_get_property(adev, "is-rv", ACPI_TYPE_INTEGER, &obj)) if (!acpi_dev_get_property(adev, "clk-name", ACPI_TYPE_STRING, &obj)) {
clk_data->is_rv = obj->integer.value; clk_data->name = devm_kzalloc(&adev->dev, obj->string.length,
GFP_KERNEL);
strcpy(clk_data->name, obj->string.pointer);
} else {
/* Set default name to mclk if entry missing in firmware */
clk_data->name = "mclk";
}
list_for_each_entry(rentry, &resource_list, node) { list_for_each_entry(rentry, &resource_list, node) {
clk_data->base = devm_ioremap(&adev->dev, rentry->res->start, clk_data->base = devm_ioremap(&adev->dev, rentry->res->start,

View File

@ -797,6 +797,12 @@ static const char * const acpi_ignore_dep_ids[] = {
NULL NULL
}; };
/* List of HIDs for which we honor deps of matching ACPI devs, when checking _DEP lists. */
static const char * const acpi_honor_dep_ids[] = {
"INT3472", /* Camera sensor PMIC / clk and regulator info */
NULL
};
static struct acpi_device *acpi_bus_get_parent(acpi_handle handle) static struct acpi_device *acpi_bus_get_parent(acpi_handle handle)
{ {
struct acpi_device *device = NULL; struct acpi_device *device = NULL;
@ -1762,8 +1768,12 @@ static void acpi_scan_dep_init(struct acpi_device *adev)
struct acpi_dep_data *dep; struct acpi_dep_data *dep;
list_for_each_entry(dep, &acpi_dep_list, node) { list_for_each_entry(dep, &acpi_dep_list, node) {
if (dep->consumer == adev->handle) if (dep->consumer == adev->handle) {
if (dep->honor_dep)
adev->flags.honor_deps = 1;
adev->dep_unmet++; adev->dep_unmet++;
}
} }
} }
@ -1967,7 +1977,7 @@ static u32 acpi_scan_check_dep(acpi_handle handle, bool check_dep)
for (count = 0, i = 0; i < dep_devices.count; i++) { for (count = 0, i = 0; i < dep_devices.count; i++) {
struct acpi_device_info *info; struct acpi_device_info *info;
struct acpi_dep_data *dep; struct acpi_dep_data *dep;
bool skip; bool skip, honor_dep;
status = acpi_get_object_info(dep_devices.handles[i], &info); status = acpi_get_object_info(dep_devices.handles[i], &info);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
@ -1976,6 +1986,7 @@ static u32 acpi_scan_check_dep(acpi_handle handle, bool check_dep)
} }
skip = acpi_info_matches_ids(info, acpi_ignore_dep_ids); skip = acpi_info_matches_ids(info, acpi_ignore_dep_ids);
honor_dep = acpi_info_matches_ids(info, acpi_honor_dep_ids);
kfree(info); kfree(info);
if (skip) if (skip)
@ -1989,6 +2000,7 @@ static u32 acpi_scan_check_dep(acpi_handle handle, bool check_dep)
dep->supplier = dep_devices.handles[i]; dep->supplier = dep_devices.handles[i];
dep->consumer = handle; dep->consumer = handle;
dep->honor_dep = honor_dep;
mutex_lock(&acpi_dep_list_lock); mutex_lock(&acpi_dep_list_lock);
list_add_tail(&dep->node , &acpi_dep_list); list_add_tail(&dep->node , &acpi_dep_list);
@ -2155,8 +2167,8 @@ static void acpi_bus_attach(struct acpi_device *device, bool first_pass)
register_dock_dependent_device(device, ejd); register_dock_dependent_device(device, ejd);
acpi_bus_get_status(device); acpi_bus_get_status(device);
/* Skip devices that are not present. */ /* Skip devices that are not ready for enumeration (e.g. not present) */
if (!acpi_device_is_present(device)) { if (!acpi_dev_ready_for_enumeration(device)) {
device->flags.initialized = false; device->flags.initialized = false;
acpi_device_clear_enumerated(device); acpi_device_clear_enumerated(device);
device->flags.power_manageable = 0; device->flags.power_manageable = 0;
@ -2318,6 +2330,23 @@ void acpi_dev_clear_dependencies(struct acpi_device *supplier)
} }
EXPORT_SYMBOL_GPL(acpi_dev_clear_dependencies); EXPORT_SYMBOL_GPL(acpi_dev_clear_dependencies);
/**
* acpi_dev_ready_for_enumeration - Check if the ACPI device is ready for enumeration
* @device: Pointer to the &struct acpi_device to check
*
* Check if the device is present and has no unmet dependencies.
*
* Return true if the device is ready for enumeratino. Otherwise, return false.
*/
bool acpi_dev_ready_for_enumeration(const struct acpi_device *device)
{
if (device->flags.honor_deps && device->dep_unmet)
return false;
return acpi_device_is_present(device);
}
EXPORT_SYMBOL_GPL(acpi_dev_ready_for_enumeration);
/** /**
* acpi_dev_get_first_consumer_dev - Return ACPI device dependent on @supplier * acpi_dev_get_first_consumer_dev - Return ACPI device dependent on @supplier
* @supplier: Pointer to the dependee device * @supplier: Pointer to the dependee device

View File

@ -169,6 +169,14 @@ config COMMON_CLK_CDCE706
help help
This driver supports TI CDCE706 programmable 3-PLL clock synthesizer. This driver supports TI CDCE706 programmable 3-PLL clock synthesizer.
config COMMON_CLK_TPS68470
tristate "Clock Driver for TI TPS68470 PMIC"
depends on I2C
depends on INTEL_SKL_INT3472 || COMPILE_TEST
select REGMAP_I2C
help
This driver supports the clocks provided by the TPS68470 PMIC.
config COMMON_CLK_CDCE925 config COMMON_CLK_CDCE925
tristate "Clock driver for TI CDCE913/925/937/949 devices" tristate "Clock driver for TI CDCE913/925/937/949 devices"
depends on I2C depends on I2C

View File

@ -64,6 +64,7 @@ obj-$(CONFIG_COMMON_CLK_SI570) += clk-si570.o
obj-$(CONFIG_COMMON_CLK_STM32F) += clk-stm32f4.o obj-$(CONFIG_COMMON_CLK_STM32F) += clk-stm32f4.o
obj-$(CONFIG_COMMON_CLK_STM32H7) += clk-stm32h7.o obj-$(CONFIG_COMMON_CLK_STM32H7) += clk-stm32h7.o
obj-$(CONFIG_COMMON_CLK_STM32MP157) += clk-stm32mp1.o obj-$(CONFIG_COMMON_CLK_STM32MP157) += clk-stm32mp1.o
obj-$(CONFIG_COMMON_CLK_TPS68470) += clk-tps68470.o
obj-$(CONFIG_CLK_TWL6040) += clk-twl6040.o obj-$(CONFIG_CLK_TWL6040) += clk-twl6040.o
obj-$(CONFIG_ARCH_VT8500) += clk-vt8500.o obj-$(CONFIG_ARCH_VT8500) += clk-vt8500.o
obj-$(CONFIG_COMMON_CLK_VC5) += clk-versaclock5.o obj-$(CONFIG_COMMON_CLK_VC5) += clk-versaclock5.o
@ -111,7 +112,7 @@ obj-$(CONFIG_PLAT_SPEAR) += spear/
obj-y += sprd/ obj-y += sprd/
obj-$(CONFIG_ARCH_STI) += st/ obj-$(CONFIG_ARCH_STI) += st/
obj-$(CONFIG_ARCH_SUNXI) += sunxi/ obj-$(CONFIG_ARCH_SUNXI) += sunxi/
obj-$(CONFIG_SUNXI_CCU) += sunxi-ng/ obj-y += sunxi-ng/
obj-$(CONFIG_ARCH_TEGRA) += tegra/ obj-$(CONFIG_ARCH_TEGRA) += tegra/
obj-y += ti/ obj-y += ti/
obj-$(CONFIG_CLK_UNIPHIER) += uniphier/ obj-$(CONFIG_CLK_UNIPHIER) += uniphier/

View File

@ -129,7 +129,6 @@ static const struct stm32f4_gate_data stm32f429_gates[] __initconst = {
{ STM32F4_RCC_APB2ENR, 20, "spi5", "apb2_div" }, { STM32F4_RCC_APB2ENR, 20, "spi5", "apb2_div" },
{ STM32F4_RCC_APB2ENR, 21, "spi6", "apb2_div" }, { STM32F4_RCC_APB2ENR, 21, "spi6", "apb2_div" },
{ STM32F4_RCC_APB2ENR, 22, "sai1", "apb2_div" }, { STM32F4_RCC_APB2ENR, 22, "sai1", "apb2_div" },
{ STM32F4_RCC_APB2ENR, 26, "ltdc", "apb2_div" },
}; };
static const struct stm32f4_gate_data stm32f469_gates[] __initconst = { static const struct stm32f4_gate_data stm32f469_gates[] __initconst = {
@ -211,7 +210,6 @@ static const struct stm32f4_gate_data stm32f469_gates[] __initconst = {
{ STM32F4_RCC_APB2ENR, 20, "spi5", "apb2_div" }, { STM32F4_RCC_APB2ENR, 20, "spi5", "apb2_div" },
{ STM32F4_RCC_APB2ENR, 21, "spi6", "apb2_div" }, { STM32F4_RCC_APB2ENR, 21, "spi6", "apb2_div" },
{ STM32F4_RCC_APB2ENR, 22, "sai1", "apb2_div" }, { STM32F4_RCC_APB2ENR, 22, "sai1", "apb2_div" },
{ STM32F4_RCC_APB2ENR, 26, "ltdc", "apb2_div" },
}; };
static const struct stm32f4_gate_data stm32f746_gates[] __initconst = { static const struct stm32f4_gate_data stm32f746_gates[] __initconst = {
@ -286,7 +284,6 @@ static const struct stm32f4_gate_data stm32f746_gates[] __initconst = {
{ STM32F4_RCC_APB2ENR, 21, "spi6", "apb2_div" }, { STM32F4_RCC_APB2ENR, 21, "spi6", "apb2_div" },
{ STM32F4_RCC_APB2ENR, 22, "sai1", "apb2_div" }, { STM32F4_RCC_APB2ENR, 22, "sai1", "apb2_div" },
{ STM32F4_RCC_APB2ENR, 23, "sai2", "apb2_div" }, { STM32F4_RCC_APB2ENR, 23, "sai2", "apb2_div" },
{ STM32F4_RCC_APB2ENR, 26, "ltdc", "apb2_div" },
}; };
static const struct stm32f4_gate_data stm32f769_gates[] __initconst = { static const struct stm32f4_gate_data stm32f769_gates[] __initconst = {
@ -364,7 +361,6 @@ static const struct stm32f4_gate_data stm32f769_gates[] __initconst = {
{ STM32F4_RCC_APB2ENR, 21, "spi6", "apb2_div" }, { STM32F4_RCC_APB2ENR, 21, "spi6", "apb2_div" },
{ STM32F4_RCC_APB2ENR, 22, "sai1", "apb2_div" }, { STM32F4_RCC_APB2ENR, 22, "sai1", "apb2_div" },
{ STM32F4_RCC_APB2ENR, 23, "sai2", "apb2_div" }, { STM32F4_RCC_APB2ENR, 23, "sai2", "apb2_div" },
{ STM32F4_RCC_APB2ENR, 26, "ltdc", "apb2_div" },
{ STM32F4_RCC_APB2ENR, 30, "mdio", "apb2_div" }, { STM32F4_RCC_APB2ENR, 30, "mdio", "apb2_div" },
}; };

261
drivers/clk/clk-tps68470.c Normal file
View File

@ -0,0 +1,261 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Clock driver for TPS68470 PMIC
*
* Copyright (c) 2021 Red Hat Inc.
* Copyright (C) 2018 Intel Corporation
*
* Authors:
* Hans de Goede <hdegoede@redhat.com>
* Zaikuo Wang <zaikuo.wang@intel.com>
* Tianshu Qiu <tian.shu.qiu@intel.com>
* Jian Xu Zheng <jian.xu.zheng@intel.com>
* Yuning Pu <yuning.pu@intel.com>
* Antti Laakso <antti.laakso@intel.com>
*/
#include <linux/clk-provider.h>
#include <linux/clkdev.h>
#include <linux/kernel.h>
#include <linux/mfd/tps68470.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/platform_data/tps68470.h>
#include <linux/regmap.h>
#define TPS68470_CLK_NAME "tps68470-clk"
#define to_tps68470_clkdata(clkd) \
container_of(clkd, struct tps68470_clkdata, clkout_hw)
static struct tps68470_clkout_freqs {
unsigned long freq;
unsigned int xtaldiv;
unsigned int plldiv;
unsigned int postdiv;
unsigned int buckdiv;
unsigned int boostdiv;
} clk_freqs[] = {
/*
* The PLL is used to multiply the crystal oscillator
* frequency range of 3 MHz to 27 MHz by a programmable
* factor of F = (M/N)*(1/P) such that the output
* available at the HCLK_A or HCLK_B pins are in the range
* of 4 MHz to 64 MHz in increments of 0.1 MHz.
*
* hclk_# = osc_in * (((plldiv*2)+320) / (xtaldiv+30)) * (1 / 2^postdiv)
*
* PLL_REF_CLK should be as close as possible to 100kHz
* PLL_REF_CLK = input clk / XTALDIV[7:0] + 30)
*
* PLL_VCO_CLK = (PLL_REF_CLK * (plldiv*2 + 320))
*
* BOOST should be as close as possible to 2Mhz
* BOOST = PLL_VCO_CLK / (BOOSTDIV[4:0] + 16) *
*
* BUCK should be as close as possible to 5.2Mhz
* BUCK = PLL_VCO_CLK / (BUCKDIV[3:0] + 5)
*
* osc_in xtaldiv plldiv postdiv hclk_#
* 20Mhz 170 32 1 19.2Mhz
* 20Mhz 170 40 1 20Mhz
* 20Mhz 170 80 1 24Mhz
*/
{ 19200000, 170, 32, 1, 2, 3 },
{ 20000000, 170, 40, 1, 3, 4 },
{ 24000000, 170, 80, 1, 4, 8 },
};
struct tps68470_clkdata {
struct clk_hw clkout_hw;
struct regmap *regmap;
unsigned long rate;
};
static int tps68470_clk_is_prepared(struct clk_hw *hw)
{
struct tps68470_clkdata *clkdata = to_tps68470_clkdata(hw);
int val;
if (regmap_read(clkdata->regmap, TPS68470_REG_PLLCTL, &val))
return 0;
return val & TPS68470_PLL_EN_MASK;
}
static int tps68470_clk_prepare(struct clk_hw *hw)
{
struct tps68470_clkdata *clkdata = to_tps68470_clkdata(hw);
regmap_write(clkdata->regmap, TPS68470_REG_CLKCFG1,
(TPS68470_PLL_OUTPUT_ENABLE << TPS68470_OUTPUT_A_SHIFT) |
(TPS68470_PLL_OUTPUT_ENABLE << TPS68470_OUTPUT_B_SHIFT));
regmap_update_bits(clkdata->regmap, TPS68470_REG_PLLCTL,
TPS68470_PLL_EN_MASK, TPS68470_PLL_EN_MASK);
/*
* The PLLCTL reg lock bit is set by the PMIC after approx. 4ms and
* does not indicate a true lock, so just wait 4 ms.
*/
usleep_range(4000, 5000);
return 0;
}
static void tps68470_clk_unprepare(struct clk_hw *hw)
{
struct tps68470_clkdata *clkdata = to_tps68470_clkdata(hw);
/* Disable clock first ... */
regmap_update_bits(clkdata->regmap, TPS68470_REG_PLLCTL, TPS68470_PLL_EN_MASK, 0);
/* ... and then tri-state the clock outputs. */
regmap_write(clkdata->regmap, TPS68470_REG_CLKCFG1, 0);
}
static unsigned long tps68470_clk_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
{
struct tps68470_clkdata *clkdata = to_tps68470_clkdata(hw);
return clkdata->rate;
}
/*
* This returns the index of the clk_freqs[] cfg with the closest rate for
* use in tps68470_clk_round_rate(). tps68470_clk_set_rate() checks that
* the rate of the returned cfg is an exact match.
*/
static unsigned int tps68470_clk_cfg_lookup(unsigned long rate)
{
long diff, best_diff = LONG_MAX;
unsigned int i, best_idx = 0;
for (i = 0; i < ARRAY_SIZE(clk_freqs); i++) {
diff = clk_freqs[i].freq - rate;
if (diff == 0)
return i;
diff = abs(diff);
if (diff < best_diff) {
best_diff = diff;
best_idx = i;
}
}
return best_idx;
}
static long tps68470_clk_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
{
unsigned int idx = tps68470_clk_cfg_lookup(rate);
return clk_freqs[idx].freq;
}
static int tps68470_clk_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
struct tps68470_clkdata *clkdata = to_tps68470_clkdata(hw);
unsigned int idx = tps68470_clk_cfg_lookup(rate);
if (rate != clk_freqs[idx].freq)
return -EINVAL;
regmap_write(clkdata->regmap, TPS68470_REG_BOOSTDIV, clk_freqs[idx].boostdiv);
regmap_write(clkdata->regmap, TPS68470_REG_BUCKDIV, clk_freqs[idx].buckdiv);
regmap_write(clkdata->regmap, TPS68470_REG_PLLSWR, TPS68470_PLLSWR_DEFAULT);
regmap_write(clkdata->regmap, TPS68470_REG_XTALDIV, clk_freqs[idx].xtaldiv);
regmap_write(clkdata->regmap, TPS68470_REG_PLLDIV, clk_freqs[idx].plldiv);
regmap_write(clkdata->regmap, TPS68470_REG_POSTDIV, clk_freqs[idx].postdiv);
regmap_write(clkdata->regmap, TPS68470_REG_POSTDIV2, clk_freqs[idx].postdiv);
regmap_write(clkdata->regmap, TPS68470_REG_CLKCFG2, TPS68470_CLKCFG2_DRV_STR_2MA);
regmap_write(clkdata->regmap, TPS68470_REG_PLLCTL,
TPS68470_OSC_EXT_CAP_DEFAULT << TPS68470_OSC_EXT_CAP_SHIFT |
TPS68470_CLK_SRC_XTAL << TPS68470_CLK_SRC_SHIFT);
clkdata->rate = rate;
return 0;
}
static const struct clk_ops tps68470_clk_ops = {
.is_prepared = tps68470_clk_is_prepared,
.prepare = tps68470_clk_prepare,
.unprepare = tps68470_clk_unprepare,
.recalc_rate = tps68470_clk_recalc_rate,
.round_rate = tps68470_clk_round_rate,
.set_rate = tps68470_clk_set_rate,
};
static int tps68470_clk_probe(struct platform_device *pdev)
{
struct tps68470_clk_platform_data *pdata = pdev->dev.platform_data;
struct clk_init_data tps68470_clk_initdata = {
.name = TPS68470_CLK_NAME,
.ops = &tps68470_clk_ops,
/* Changing the dividers when the PLL is on is not allowed */
.flags = CLK_SET_RATE_GATE,
};
struct tps68470_clkdata *tps68470_clkdata;
int ret;
tps68470_clkdata = devm_kzalloc(&pdev->dev, sizeof(*tps68470_clkdata),
GFP_KERNEL);
if (!tps68470_clkdata)
return -ENOMEM;
tps68470_clkdata->regmap = dev_get_drvdata(pdev->dev.parent);
tps68470_clkdata->clkout_hw.init = &tps68470_clk_initdata;
/* Set initial rate */
tps68470_clk_set_rate(&tps68470_clkdata->clkout_hw, clk_freqs[0].freq, 0);
ret = devm_clk_hw_register(&pdev->dev, &tps68470_clkdata->clkout_hw);
if (ret)
return ret;
ret = devm_clk_hw_register_clkdev(&pdev->dev, &tps68470_clkdata->clkout_hw,
TPS68470_CLK_NAME, NULL);
if (ret)
return ret;
if (pdata) {
ret = devm_clk_hw_register_clkdev(&pdev->dev,
&tps68470_clkdata->clkout_hw,
pdata->consumer_con_id,
pdata->consumer_dev_name);
}
return ret;
}
static struct platform_driver tps68470_clk_driver = {
.driver = {
.name = TPS68470_CLK_NAME,
},
.probe = tps68470_clk_probe,
};
/*
* The ACPI tps68470 probe-ordering depends on the clk/gpio/regulator drivers
* registering before the drivers for the camera-sensors which use them bind.
* subsys_initcall() ensures this when the drivers are builtin.
*/
static int __init tps68470_clk_init(void)
{
return platform_driver_register(&tps68470_clk_driver);
}
subsys_initcall(tps68470_clk_init);
static void __exit tps68470_clk_exit(void)
{
platform_driver_unregister(&tps68470_clk_driver);
}
module_exit(tps68470_clk_exit);
MODULE_ALIAS("platform:tps68470-clk");
MODULE_DESCRIPTION("clock driver for TPS68470 pmic");
MODULE_LICENSE("GPL");

View File

@ -713,6 +713,35 @@ static struct clk_regmap gxbb_mpll_prediv = {
}; };
static struct clk_regmap gxbb_mpll0_div = { static struct clk_regmap gxbb_mpll0_div = {
.data = &(struct meson_clk_mpll_data){
.sdm = {
.reg_off = HHI_MPLL_CNTL7,
.shift = 0,
.width = 14,
},
.sdm_en = {
.reg_off = HHI_MPLL_CNTL,
.shift = 25,
.width = 1,
},
.n2 = {
.reg_off = HHI_MPLL_CNTL7,
.shift = 16,
.width = 9,
},
.lock = &meson_clk_lock,
},
.hw.init = &(struct clk_init_data){
.name = "mpll0_div",
.ops = &meson_clk_mpll_ops,
.parent_hws = (const struct clk_hw *[]) {
&gxbb_mpll_prediv.hw
},
.num_parents = 1,
},
};
static struct clk_regmap gxl_mpll0_div = {
.data = &(struct meson_clk_mpll_data){ .data = &(struct meson_clk_mpll_data){
.sdm = { .sdm = {
.reg_off = HHI_MPLL_CNTL7, .reg_off = HHI_MPLL_CNTL7,
@ -749,7 +778,16 @@ static struct clk_regmap gxbb_mpll0 = {
.hw.init = &(struct clk_init_data){ .hw.init = &(struct clk_init_data){
.name = "mpll0", .name = "mpll0",
.ops = &clk_regmap_gate_ops, .ops = &clk_regmap_gate_ops,
.parent_hws = (const struct clk_hw *[]) { &gxbb_mpll0_div.hw }, .parent_data = &(const struct clk_parent_data) {
/*
* Note:
* GXL and GXBB have different SDM_EN registers. We
* fallback to the global naming string mechanism so
* mpll0_div picks up the appropriate one.
*/
.name = "mpll0_div",
.index = -1,
},
.num_parents = 1, .num_parents = 1,
.flags = CLK_SET_RATE_PARENT, .flags = CLK_SET_RATE_PARENT,
}, },
@ -3044,7 +3082,7 @@ static struct clk_hw_onecell_data gxl_hw_onecell_data = {
[CLKID_VAPB_1] = &gxbb_vapb_1.hw, [CLKID_VAPB_1] = &gxbb_vapb_1.hw,
[CLKID_VAPB_SEL] = &gxbb_vapb_sel.hw, [CLKID_VAPB_SEL] = &gxbb_vapb_sel.hw,
[CLKID_VAPB] = &gxbb_vapb.hw, [CLKID_VAPB] = &gxbb_vapb.hw,
[CLKID_MPLL0_DIV] = &gxbb_mpll0_div.hw, [CLKID_MPLL0_DIV] = &gxl_mpll0_div.hw,
[CLKID_MPLL1_DIV] = &gxbb_mpll1_div.hw, [CLKID_MPLL1_DIV] = &gxbb_mpll1_div.hw,
[CLKID_MPLL2_DIV] = &gxbb_mpll2_div.hw, [CLKID_MPLL2_DIV] = &gxbb_mpll2_div.hw,
[CLKID_MPLL_PREDIV] = &gxbb_mpll_prediv.hw, [CLKID_MPLL_PREDIV] = &gxbb_mpll_prediv.hw,
@ -3439,7 +3477,7 @@ static struct clk_regmap *const gxl_clk_regmaps[] = {
&gxbb_mpll0, &gxbb_mpll0,
&gxbb_mpll1, &gxbb_mpll1,
&gxbb_mpll2, &gxbb_mpll2,
&gxbb_mpll0_div, &gxl_mpll0_div,
&gxbb_mpll1_div, &gxbb_mpll1_div,
&gxbb_mpll2_div, &gxbb_mpll2_div,
&gxbb_cts_amclk_div, &gxbb_cts_amclk_div,

View File

@ -1,6 +1,6 @@
# SPDX-License-Identifier: GPL-2.0-only # SPDX-License-Identifier: GPL-2.0-only
config SUNXI_CCU config SUNXI_CCU
bool "Clock support for Allwinner SoCs" tristate "Clock support for Allwinner SoCs"
depends on ARCH_SUNXI || COMPILE_TEST depends on ARCH_SUNXI || COMPILE_TEST
select RESET_CONTROLLER select RESET_CONTROLLER
default ARCH_SUNXI default ARCH_SUNXI
@ -8,42 +8,52 @@ config SUNXI_CCU
if SUNXI_CCU if SUNXI_CCU
config SUNIV_F1C100S_CCU config SUNIV_F1C100S_CCU
bool "Support for the Allwinner newer F1C100s CCU" tristate "Support for the Allwinner newer F1C100s CCU"
default MACH_SUNIV default MACH_SUNIV
depends on MACH_SUNIV || COMPILE_TEST depends on MACH_SUNIV || COMPILE_TEST
config SUN20I_D1_CCU
tristate "Support for the Allwinner D1 CCU"
default RISCV && ARCH_SUNXI
depends on (RISCV && ARCH_SUNXI) || COMPILE_TEST
config SUN20I_D1_R_CCU
tristate "Support for the Allwinner D1 PRCM CCU"
default RISCV && ARCH_SUNXI
depends on (RISCV && ARCH_SUNXI) || COMPILE_TEST
config SUN50I_A64_CCU config SUN50I_A64_CCU
bool "Support for the Allwinner A64 CCU" tristate "Support for the Allwinner A64 CCU"
default ARM64 && ARCH_SUNXI default ARM64 && ARCH_SUNXI
depends on (ARM64 && ARCH_SUNXI) || COMPILE_TEST depends on (ARM64 && ARCH_SUNXI) || COMPILE_TEST
config SUN50I_A100_CCU config SUN50I_A100_CCU
bool "Support for the Allwinner A100 CCU" tristate "Support for the Allwinner A100 CCU"
default ARM64 && ARCH_SUNXI default ARM64 && ARCH_SUNXI
depends on (ARM64 && ARCH_SUNXI) || COMPILE_TEST depends on (ARM64 && ARCH_SUNXI) || COMPILE_TEST
config SUN50I_A100_R_CCU config SUN50I_A100_R_CCU
bool "Support for the Allwinner A100 PRCM CCU" tristate "Support for the Allwinner A100 PRCM CCU"
default ARM64 && ARCH_SUNXI default ARM64 && ARCH_SUNXI
depends on (ARM64 && ARCH_SUNXI) || COMPILE_TEST depends on (ARM64 && ARCH_SUNXI) || COMPILE_TEST
config SUN50I_H6_CCU config SUN50I_H6_CCU
bool "Support for the Allwinner H6 CCU" tristate "Support for the Allwinner H6 CCU"
default ARM64 && ARCH_SUNXI default ARM64 && ARCH_SUNXI
depends on (ARM64 && ARCH_SUNXI) || COMPILE_TEST depends on (ARM64 && ARCH_SUNXI) || COMPILE_TEST
config SUN50I_H616_CCU config SUN50I_H616_CCU
bool "Support for the Allwinner H616 CCU" tristate "Support for the Allwinner H616 CCU"
default ARM64 && ARCH_SUNXI default ARM64 && ARCH_SUNXI
depends on (ARM64 && ARCH_SUNXI) || COMPILE_TEST depends on (ARM64 && ARCH_SUNXI) || COMPILE_TEST
config SUN50I_H6_R_CCU config SUN50I_H6_R_CCU
bool "Support for the Allwinner H6 and H616 PRCM CCU" tristate "Support for the Allwinner H6 and H616 PRCM CCU"
default ARM64 && ARCH_SUNXI default ARM64 && ARCH_SUNXI
depends on (ARM64 && ARCH_SUNXI) || COMPILE_TEST depends on (ARM64 && ARCH_SUNXI) || COMPILE_TEST
config SUN4I_A10_CCU config SUN4I_A10_CCU
bool "Support for the Allwinner A10/A20 CCU" tristate "Support for the Allwinner A10/A20 CCU"
default MACH_SUN4I default MACH_SUN4I
default MACH_SUN7I default MACH_SUN7I
depends on MACH_SUN4I || MACH_SUN7I || COMPILE_TEST depends on MACH_SUN4I || MACH_SUN7I || COMPILE_TEST
@ -52,53 +62,54 @@ config SUN5I_CCU
bool "Support for the Allwinner sun5i family CCM" bool "Support for the Allwinner sun5i family CCM"
default MACH_SUN5I default MACH_SUN5I
depends on MACH_SUN5I || COMPILE_TEST depends on MACH_SUN5I || COMPILE_TEST
depends on SUNXI_CCU=y
config SUN6I_A31_CCU config SUN6I_A31_CCU
bool "Support for the Allwinner A31/A31s CCU" tristate "Support for the Allwinner A31/A31s CCU"
default MACH_SUN6I default MACH_SUN6I
depends on MACH_SUN6I || COMPILE_TEST depends on MACH_SUN6I || COMPILE_TEST
config SUN8I_A23_CCU config SUN8I_A23_CCU
bool "Support for the Allwinner A23 CCU" tristate "Support for the Allwinner A23 CCU"
default MACH_SUN8I default MACH_SUN8I
depends on MACH_SUN8I || COMPILE_TEST depends on MACH_SUN8I || COMPILE_TEST
config SUN8I_A33_CCU config SUN8I_A33_CCU
bool "Support for the Allwinner A33 CCU" tristate "Support for the Allwinner A33 CCU"
default MACH_SUN8I default MACH_SUN8I
depends on MACH_SUN8I || COMPILE_TEST depends on MACH_SUN8I || COMPILE_TEST
config SUN8I_A83T_CCU config SUN8I_A83T_CCU
bool "Support for the Allwinner A83T CCU" tristate "Support for the Allwinner A83T CCU"
default MACH_SUN8I default MACH_SUN8I
depends on MACH_SUN8I || COMPILE_TEST depends on MACH_SUN8I || COMPILE_TEST
config SUN8I_H3_CCU config SUN8I_H3_CCU
bool "Support for the Allwinner H3 CCU" tristate "Support for the Allwinner H3 CCU"
default MACH_SUN8I || (ARM64 && ARCH_SUNXI) default MACH_SUN8I || (ARM64 && ARCH_SUNXI)
depends on MACH_SUN8I || (ARM64 && ARCH_SUNXI) || COMPILE_TEST depends on MACH_SUN8I || (ARM64 && ARCH_SUNXI) || COMPILE_TEST
config SUN8I_V3S_CCU config SUN8I_V3S_CCU
bool "Support for the Allwinner V3s CCU" tristate "Support for the Allwinner V3s CCU"
default MACH_SUN8I default MACH_SUN8I
depends on MACH_SUN8I || COMPILE_TEST depends on MACH_SUN8I || COMPILE_TEST
config SUN8I_DE2_CCU config SUN8I_DE2_CCU
bool "Support for the Allwinner SoCs DE2 CCU" tristate "Support for the Allwinner SoCs DE2 CCU"
default MACH_SUN8I || (ARM64 && ARCH_SUNXI) default MACH_SUN8I || (ARM64 && ARCH_SUNXI)
config SUN8I_R40_CCU config SUN8I_R40_CCU
bool "Support for the Allwinner R40 CCU" tristate "Support for the Allwinner R40 CCU"
default MACH_SUN8I default MACH_SUN8I
depends on MACH_SUN8I || COMPILE_TEST depends on MACH_SUN8I || COMPILE_TEST
config SUN9I_A80_CCU config SUN9I_A80_CCU
bool "Support for the Allwinner A80 CCU" tristate "Support for the Allwinner A80 CCU"
default MACH_SUN9I default MACH_SUN9I
depends on MACH_SUN9I || COMPILE_TEST depends on MACH_SUN9I || COMPILE_TEST
config SUN8I_R_CCU config SUN8I_R_CCU
bool "Support for Allwinner SoCs' PRCM CCUs" tristate "Support for Allwinner SoCs' PRCM CCUs"
default MACH_SUN8I || (ARCH_SUNXI && ARM64) default MACH_SUN8I || (ARCH_SUNXI && ARM64)
endif endif

View File

@ -1,44 +1,73 @@
# SPDX-License-Identifier: GPL-2.0 # SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_SUNXI_CCU) += sunxi-ccu.o
# Common objects # Common objects
obj-y += ccu_common.o sunxi-ccu-y += ccu_common.o
obj-y += ccu_mmc_timing.o sunxi-ccu-y += ccu_mmc_timing.o
obj-y += ccu_reset.o sunxi-ccu-y += ccu_reset.o
# Base clock types # Base clock types
obj-y += ccu_div.o sunxi-ccu-y += ccu_div.o
obj-y += ccu_frac.o sunxi-ccu-y += ccu_frac.o
obj-y += ccu_gate.o sunxi-ccu-y += ccu_gate.o
obj-y += ccu_mux.o sunxi-ccu-y += ccu_mux.o
obj-y += ccu_mult.o sunxi-ccu-y += ccu_mult.o
obj-y += ccu_phase.o sunxi-ccu-y += ccu_phase.o
obj-y += ccu_sdm.o sunxi-ccu-y += ccu_sdm.o
# Multi-factor clocks # Multi-factor clocks
obj-y += ccu_nk.o sunxi-ccu-y += ccu_nk.o
obj-y += ccu_nkm.o sunxi-ccu-y += ccu_nkm.o
obj-y += ccu_nkmp.o sunxi-ccu-y += ccu_nkmp.o
obj-y += ccu_nm.o sunxi-ccu-y += ccu_nm.o
obj-y += ccu_mp.o sunxi-ccu-y += ccu_mp.o
# SoC support # SoC support
obj-$(CONFIG_SUNIV_F1C100S_CCU) += ccu-suniv-f1c100s.o obj-$(CONFIG_SUNIV_F1C100S_CCU) += suniv-f1c100s-ccu.o
obj-$(CONFIG_SUN50I_A64_CCU) += ccu-sun50i-a64.o obj-$(CONFIG_SUN20I_D1_CCU) += sun20i-d1-ccu.o
obj-$(CONFIG_SUN50I_A100_CCU) += ccu-sun50i-a100.o obj-$(CONFIG_SUN20I_D1_R_CCU) += sun20i-d1-r-ccu.o
obj-$(CONFIG_SUN50I_A100_R_CCU) += ccu-sun50i-a100-r.o obj-$(CONFIG_SUN50I_A64_CCU) += sun50i-a64-ccu.o
obj-$(CONFIG_SUN50I_H6_CCU) += ccu-sun50i-h6.o obj-$(CONFIG_SUN50I_A100_CCU) += sun50i-a100-ccu.o
obj-$(CONFIG_SUN50I_H616_CCU) += ccu-sun50i-h616.o obj-$(CONFIG_SUN50I_A100_R_CCU) += sun50i-a100-r-ccu.o
obj-$(CONFIG_SUN50I_H6_R_CCU) += ccu-sun50i-h6-r.o obj-$(CONFIG_SUN50I_H6_CCU) += sun50i-h6-ccu.o
obj-$(CONFIG_SUN4I_A10_CCU) += ccu-sun4i-a10.o obj-$(CONFIG_SUN50I_H6_R_CCU) += sun50i-h6-r-ccu.o
obj-$(CONFIG_SUN5I_CCU) += ccu-sun5i.o obj-$(CONFIG_SUN50I_H616_CCU) += sun50i-h616-ccu.o
obj-$(CONFIG_SUN6I_A31_CCU) += ccu-sun6i-a31.o obj-$(CONFIG_SUN4I_A10_CCU) += sun4i-a10-ccu.o
obj-$(CONFIG_SUN8I_A23_CCU) += ccu-sun8i-a23.o obj-$(CONFIG_SUN5I_CCU) += sun5i-ccu.o
obj-$(CONFIG_SUN8I_A33_CCU) += ccu-sun8i-a33.o obj-$(CONFIG_SUN6I_A31_CCU) += sun6i-a31-ccu.o
obj-$(CONFIG_SUN8I_A83T_CCU) += ccu-sun8i-a83t.o obj-$(CONFIG_SUN8I_A23_CCU) += sun8i-a23-ccu.o
obj-$(CONFIG_SUN8I_H3_CCU) += ccu-sun8i-h3.o obj-$(CONFIG_SUN8I_A33_CCU) += sun8i-a33-ccu.o
obj-$(CONFIG_SUN8I_V3S_CCU) += ccu-sun8i-v3s.o obj-$(CONFIG_SUN8I_A83T_CCU) += sun8i-a83t-ccu.o
obj-$(CONFIG_SUN8I_DE2_CCU) += ccu-sun8i-de2.o obj-$(CONFIG_SUN8I_H3_CCU) += sun8i-h3-ccu.o
obj-$(CONFIG_SUN8I_R_CCU) += ccu-sun8i-r.o obj-$(CONFIG_SUN8I_R40_CCU) += sun8i-r40-ccu.o
obj-$(CONFIG_SUN8I_R40_CCU) += ccu-sun8i-r40.o obj-$(CONFIG_SUN8I_V3S_CCU) += sun8i-v3s-ccu.o
obj-$(CONFIG_SUN9I_A80_CCU) += ccu-sun9i-a80.o obj-$(CONFIG_SUN8I_DE2_CCU) += sun8i-de2-ccu.o
obj-$(CONFIG_SUN9I_A80_CCU) += ccu-sun9i-a80-de.o obj-$(CONFIG_SUN8I_R_CCU) += sun8i-r-ccu.o
obj-$(CONFIG_SUN9I_A80_CCU) += ccu-sun9i-a80-usb.o obj-$(CONFIG_SUN9I_A80_CCU) += sun9i-a80-ccu.o
obj-$(CONFIG_SUN9I_A80_CCU) += sun9i-a80-de-ccu.o
obj-$(CONFIG_SUN9I_A80_CCU) += sun9i-a80-usb-ccu.o
suniv-f1c100s-ccu-y += ccu-suniv-f1c100s.o
sun20i-d1-ccu-y += ccu-sun20i-d1.o
sun20i-d1-r-ccu-y += ccu-sun20i-d1-r.o
sun50i-a64-ccu-y += ccu-sun50i-a64.o
sun50i-a100-ccu-y += ccu-sun50i-a100.o
sun50i-a100-r-ccu-y += ccu-sun50i-a100-r.o
sun50i-h6-ccu-y += ccu-sun50i-h6.o
sun50i-h6-r-ccu-y += ccu-sun50i-h6-r.o
sun50i-h616-ccu-y += ccu-sun50i-h616.o
sun4i-a10-ccu-y += ccu-sun4i-a10.o
sun5i-ccu-y += ccu-sun5i.o
sun6i-a31-ccu-y += ccu-sun6i-a31.o
sun8i-a23-ccu-y += ccu-sun8i-a23.o
sun8i-a33-ccu-y += ccu-sun8i-a33.o
sun8i-a83t-ccu-y += ccu-sun8i-a83t.o
sun8i-h3-ccu-y += ccu-sun8i-h3.o
sun8i-r40-ccu-y += ccu-sun8i-r40.o
sun8i-v3s-ccu-y += ccu-sun8i-v3s.o
sun8i-de2-ccu-y += ccu-sun8i-de2.o
sun8i-r-ccu-y += ccu-sun8i-r.o
sun9i-a80-ccu-y += ccu-sun9i-a80.o
sun9i-a80-de-ccu-y += ccu-sun9i-a80-de.o
sun9i-a80-usb-ccu-y += ccu-sun9i-a80-usb.o

View File

@ -0,0 +1,140 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2020 huangzhenwei@allwinnertech.com
* Copyright (C) 2021 Samuel Holland <samuel@sholland.org>
*/
#include <linux/clk-provider.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include "ccu_common.h"
#include "ccu_reset.h"
#include "ccu_gate.h"
#include "ccu_mp.h"
#include "ccu-sun20i-d1-r.h"
static const struct clk_parent_data r_ahb_apb0_parents[] = {
{ .fw_name = "hosc" },
{ .fw_name = "losc" },
{ .fw_name = "iosc" },
{ .fw_name = "pll-periph" },
};
static SUNXI_CCU_MP_DATA_WITH_MUX(r_ahb_clk, "r-ahb",
r_ahb_apb0_parents, 0x000,
0, 5, /* M */
8, 2, /* P */
24, 3, /* mux */
0);
static const struct clk_hw *r_ahb_hw = &r_ahb_clk.common.hw;
static SUNXI_CCU_MP_DATA_WITH_MUX(r_apb0_clk, "r-apb0",
r_ahb_apb0_parents, 0x00c,
0, 5, /* M */
8, 2, /* P */
24, 3, /* mux */
0);
static const struct clk_hw *r_apb0_hw = &r_apb0_clk.common.hw;
static SUNXI_CCU_GATE_HWS(bus_r_timer_clk, "bus-r-timer", &r_apb0_hw,
0x11c, BIT(0), 0);
static SUNXI_CCU_GATE_HWS(bus_r_twd_clk, "bus-r-twd", &r_apb0_hw,
0x12c, BIT(0), 0);
static SUNXI_CCU_GATE_HWS(bus_r_ppu_clk, "bus-r-ppu", &r_apb0_hw,
0x1ac, BIT(0), 0);
static const struct clk_parent_data r_ir_rx_parents[] = {
{ .fw_name = "losc" },
{ .fw_name = "hosc" },
};
static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(r_ir_rx_clk, "r-ir-rx",
r_ir_rx_parents, 0x1c0,
0, 5, /* M */
8, 2, /* P */
24, 2, /* mux */
BIT(31), /* gate */
0);
static SUNXI_CCU_GATE_HWS(bus_r_ir_rx_clk, "bus-r-ir-rx", &r_apb0_hw,
0x1cc, BIT(0), 0);
static SUNXI_CCU_GATE_HWS(bus_r_rtc_clk, "bus-r-rtc", &r_ahb_hw,
0x20c, BIT(0), 0);
static SUNXI_CCU_GATE_HWS(bus_r_cpucfg_clk, "bus-r-cpucfg", &r_apb0_hw,
0x22c, BIT(0), 0);
static struct ccu_common *sun20i_d1_r_ccu_clks[] = {
&r_ahb_clk.common,
&r_apb0_clk.common,
&bus_r_timer_clk.common,
&bus_r_twd_clk.common,
&bus_r_ppu_clk.common,
&r_ir_rx_clk.common,
&bus_r_ir_rx_clk.common,
&bus_r_rtc_clk.common,
&bus_r_cpucfg_clk.common,
};
static struct clk_hw_onecell_data sun20i_d1_r_hw_clks = {
.num = CLK_NUMBER,
.hws = {
[CLK_R_AHB] = &r_ahb_clk.common.hw,
[CLK_R_APB0] = &r_apb0_clk.common.hw,
[CLK_BUS_R_TIMER] = &bus_r_timer_clk.common.hw,
[CLK_BUS_R_TWD] = &bus_r_twd_clk.common.hw,
[CLK_BUS_R_PPU] = &bus_r_ppu_clk.common.hw,
[CLK_R_IR_RX] = &r_ir_rx_clk.common.hw,
[CLK_BUS_R_IR_RX] = &bus_r_ir_rx_clk.common.hw,
[CLK_BUS_R_RTC] = &bus_r_rtc_clk.common.hw,
[CLK_BUS_R_CPUCFG] = &bus_r_cpucfg_clk.common.hw,
},
};
static struct ccu_reset_map sun20i_d1_r_ccu_resets[] = {
[RST_BUS_R_TIMER] = { 0x11c, BIT(16) },
[RST_BUS_R_TWD] = { 0x12c, BIT(16) },
[RST_BUS_R_PPU] = { 0x1ac, BIT(16) },
[RST_BUS_R_IR_RX] = { 0x1cc, BIT(16) },
[RST_BUS_R_RTC] = { 0x20c, BIT(16) },
[RST_BUS_R_CPUCFG] = { 0x22c, BIT(16) },
};
static const struct sunxi_ccu_desc sun20i_d1_r_ccu_desc = {
.ccu_clks = sun20i_d1_r_ccu_clks,
.num_ccu_clks = ARRAY_SIZE(sun20i_d1_r_ccu_clks),
.hw_clks = &sun20i_d1_r_hw_clks,
.resets = sun20i_d1_r_ccu_resets,
.num_resets = ARRAY_SIZE(sun20i_d1_r_ccu_resets),
};
static int sun20i_d1_r_ccu_probe(struct platform_device *pdev)
{
void __iomem *reg;
reg = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(reg))
return PTR_ERR(reg);
return devm_sunxi_ccu_probe(&pdev->dev, reg, &sun20i_d1_r_ccu_desc);
}
static const struct of_device_id sun20i_d1_r_ccu_ids[] = {
{ .compatible = "allwinner,sun20i-d1-r-ccu" },
{ }
};
static struct platform_driver sun20i_d1_r_ccu_driver = {
.probe = sun20i_d1_r_ccu_probe,
.driver = {
.name = "sun20i-d1-r-ccu",
.suppress_bind_attrs = true,
.of_match_table = sun20i_d1_r_ccu_ids,
},
};
module_platform_driver(sun20i_d1_r_ccu_driver);
MODULE_IMPORT_NS(SUNXI_CCU);
MODULE_LICENSE("GPL");

View File

@ -0,0 +1,17 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) 2020 frank@allwinnertech.com
* Copyright (C) 2021 Samuel Holland <samuel@sholland.org>
*/
#ifndef _CCU_SUN20I_D1_R_H
#define _CCU_SUN20I_D1_R_H
#include <dt-bindings/clock/sun20i-d1-r-ccu.h>
#include <dt-bindings/reset/sun20i-d1-r-ccu.h>
#define CLK_R_APB0 1
#define CLK_NUMBER (CLK_BUS_R_CPUCFG + 1)
#endif /* _CCU_SUN20I_D1_R_H */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,15 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) 2020 frank@allwinnertech.com
* Copyright (C) 2021 Samuel Holland <samuel@sholland.org>
*/
#ifndef _CCU_SUN20I_D1_H_
#define _CCU_SUN20I_D1_H_
#include <dt-bindings/clock/sun20i-d1-ccu.h>
#include <dt-bindings/reset/sun20i-d1-ccu.h>
#define CLK_NUMBER (CLK_FANOUT2 + 1)
#endif /* _CCU_SUN20I_D1_H_ */

View File

@ -7,7 +7,9 @@
#include <linux/clk-provider.h> #include <linux/clk-provider.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/of_address.h> #include <linux/module.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include "ccu_common.h" #include "ccu_common.h"
#include "ccu_reset.h" #include "ccu_reset.h"
@ -1425,18 +1427,19 @@ static const struct sunxi_ccu_desc sun7i_a20_ccu_desc = {
.num_resets = ARRAY_SIZE(sunxi_a10_a20_ccu_resets), .num_resets = ARRAY_SIZE(sunxi_a10_a20_ccu_resets),
}; };
static void __init sun4i_ccu_init(struct device_node *node, static int sun4i_a10_ccu_probe(struct platform_device *pdev)
const struct sunxi_ccu_desc *desc)
{ {
const struct sunxi_ccu_desc *desc;
void __iomem *reg; void __iomem *reg;
u32 val; u32 val;
reg = of_io_request_and_map(node, 0, of_node_full_name(node)); desc = of_device_get_match_data(&pdev->dev);
if (IS_ERR(reg)) { if (!desc)
pr_err("%s: Could not map the clock registers\n", return -EINVAL;
of_node_full_name(node));
return; reg = devm_platform_ioremap_resource(pdev, 0);
} if (IS_ERR(reg))
return PTR_ERR(reg);
val = readl(reg + SUN4I_PLL_AUDIO_REG); val = readl(reg + SUN4I_PLL_AUDIO_REG);
@ -1464,19 +1467,30 @@ static void __init sun4i_ccu_init(struct device_node *node,
val &= ~GENMASK(7, 6); val &= ~GENMASK(7, 6);
writel(val | (2 << 6), reg + SUN4I_AHB_REG); writel(val | (2 << 6), reg + SUN4I_AHB_REG);
of_sunxi_ccu_probe(node, reg, desc); return devm_sunxi_ccu_probe(&pdev->dev, reg, desc);
} }
static void __init sun4i_a10_ccu_setup(struct device_node *node) static const struct of_device_id sun4i_a10_ccu_ids[] = {
{ {
sun4i_ccu_init(node, &sun4i_a10_ccu_desc); .compatible = "allwinner,sun4i-a10-ccu",
} .data = &sun4i_a10_ccu_desc,
CLK_OF_DECLARE(sun4i_a10_ccu, "allwinner,sun4i-a10-ccu", },
sun4i_a10_ccu_setup); {
.compatible = "allwinner,sun7i-a20-ccu",
.data = &sun7i_a20_ccu_desc,
},
{ }
};
static void __init sun7i_a20_ccu_setup(struct device_node *node) static struct platform_driver sun4i_a10_ccu_driver = {
{ .probe = sun4i_a10_ccu_probe,
sun4i_ccu_init(node, &sun7i_a20_ccu_desc); .driver = {
} .name = "sun4i-a10-ccu",
CLK_OF_DECLARE(sun7i_a20_ccu, "allwinner,sun7i-a20-ccu", .suppress_bind_attrs = true,
sun7i_a20_ccu_setup); .of_match_table = sun4i_a10_ccu_ids,
},
};
module_platform_driver(sun4i_a10_ccu_driver);
MODULE_IMPORT_NS(SUNXI_CCU);
MODULE_LICENSE("GPL");

View File

@ -5,7 +5,6 @@
#include <linux/clk-provider.h> #include <linux/clk-provider.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/of_address.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include "ccu_common.h" #include "ccu_common.h"
@ -213,3 +212,6 @@ static struct platform_driver sun50i_a100_r_ccu_driver = {
}, },
}; };
module_platform_driver(sun50i_a100_r_ccu_driver); module_platform_driver(sun50i_a100_r_ccu_driver);
MODULE_IMPORT_NS(SUNXI_CCU);
MODULE_LICENSE("GPL");

View File

@ -6,7 +6,6 @@
#include <linux/clk-provider.h> #include <linux/clk-provider.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/of_address.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include "ccu_common.h" #include "ccu_common.h"
@ -1275,3 +1274,6 @@ static struct platform_driver sun50i_a100_ccu_driver = {
}, },
}; };
module_platform_driver(sun50i_a100_ccu_driver); module_platform_driver(sun50i_a100_ccu_driver);
MODULE_IMPORT_NS(SUNXI_CCU);
MODULE_LICENSE("GPL");

View File

@ -5,7 +5,7 @@
#include <linux/clk-provider.h> #include <linux/clk-provider.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/of_address.h> #include <linux/module.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include "ccu_common.h" #include "ccu_common.h"
@ -980,4 +980,7 @@ static struct platform_driver sun50i_a64_ccu_driver = {
.of_match_table = sun50i_a64_ccu_ids, .of_match_table = sun50i_a64_ccu_ids,
}, },
}; };
builtin_platform_driver(sun50i_a64_ccu_driver); module_platform_driver(sun50i_a64_ccu_driver);
MODULE_IMPORT_NS(SUNXI_CCU);
MODULE_LICENSE("GPL");

View File

@ -4,7 +4,8 @@
*/ */
#include <linux/clk-provider.h> #include <linux/clk-provider.h>
#include <linux/of_address.h> #include <linux/module.h>
#include <linux/of_device.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include "ccu_common.h" #include "ccu_common.h"
@ -221,30 +222,43 @@ static const struct sunxi_ccu_desc sun50i_h616_r_ccu_desc = {
.num_resets = ARRAY_SIZE(sun50i_h616_r_ccu_resets), .num_resets = ARRAY_SIZE(sun50i_h616_r_ccu_resets),
}; };
static void __init sunxi_r_ccu_init(struct device_node *node, static int sun50i_h6_r_ccu_probe(struct platform_device *pdev)
const struct sunxi_ccu_desc *desc)
{ {
const struct sunxi_ccu_desc *desc;
void __iomem *reg; void __iomem *reg;
reg = of_io_request_and_map(node, 0, of_node_full_name(node)); desc = of_device_get_match_data(&pdev->dev);
if (IS_ERR(reg)) { if (!desc)
pr_err("%pOF: Could not map the clock registers\n", node); return -EINVAL;
return;
}
of_sunxi_ccu_probe(node, reg, desc); reg = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(reg))
return PTR_ERR(reg);
return devm_sunxi_ccu_probe(&pdev->dev, reg, desc);
} }
static void __init sun50i_h6_r_ccu_setup(struct device_node *node) static const struct of_device_id sun50i_h6_r_ccu_ids[] = {
{ {
sunxi_r_ccu_init(node, &sun50i_h6_r_ccu_desc); .compatible = "allwinner,sun50i-h6-r-ccu",
} .data = &sun50i_h6_r_ccu_desc,
CLK_OF_DECLARE(sun50i_h6_r_ccu, "allwinner,sun50i-h6-r-ccu", },
sun50i_h6_r_ccu_setup); {
.compatible = "allwinner,sun50i-h616-r-ccu",
.data = &sun50i_h616_r_ccu_desc,
},
{ }
};
static void __init sun50i_h616_r_ccu_setup(struct device_node *node) static struct platform_driver sun50i_h6_r_ccu_driver = {
{ .probe = sun50i_h6_r_ccu_probe,
sunxi_r_ccu_init(node, &sun50i_h616_r_ccu_desc); .driver = {
} .name = "sun50i-h6-r-ccu",
CLK_OF_DECLARE(sun50i_h616_r_ccu, "allwinner,sun50i-h616-r-ccu", .suppress_bind_attrs = true,
sun50i_h616_r_ccu_setup); .of_match_table = sun50i_h6_r_ccu_ids,
},
};
module_platform_driver(sun50i_h6_r_ccu_driver);
MODULE_IMPORT_NS(SUNXI_CCU);
MODULE_LICENSE("GPL");

View File

@ -5,7 +5,7 @@
#include <linux/clk-provider.h> #include <linux/clk-provider.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/of_address.h> #include <linux/module.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include "ccu_common.h" #include "ccu_common.h"
@ -1254,4 +1254,7 @@ static struct platform_driver sun50i_h6_ccu_driver = {
.of_match_table = sun50i_h6_ccu_ids, .of_match_table = sun50i_h6_ccu_ids,
}, },
}; };
builtin_platform_driver(sun50i_h6_ccu_driver); module_platform_driver(sun50i_h6_ccu_driver);
MODULE_IMPORT_NS(SUNXI_CCU);
MODULE_LICENSE("GPL");

View File

@ -7,7 +7,7 @@
#include <linux/clk-provider.h> #include <linux/clk-provider.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/of_address.h> #include <linux/module.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include "ccu_common.h" #include "ccu_common.h"
@ -1082,17 +1082,15 @@ static const u32 usb2_clk_regs[] = {
SUN50I_H616_USB3_CLK_REG, SUN50I_H616_USB3_CLK_REG,
}; };
static void __init sun50i_h616_ccu_setup(struct device_node *node) static int sun50i_h616_ccu_probe(struct platform_device *pdev)
{ {
void __iomem *reg; void __iomem *reg;
u32 val; u32 val;
int i; int i;
reg = of_io_request_and_map(node, 0, of_node_full_name(node)); reg = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(reg)) { if (IS_ERR(reg))
pr_err("%pOF: Could not map clock registers\n", node); return PTR_ERR(reg);
return;
}
/* Enable the lock bits and the output enable bits on all PLLs */ /* Enable the lock bits and the output enable bits on all PLLs */
for (i = 0; i < ARRAY_SIZE(pll_regs); i++) { for (i = 0; i < ARRAY_SIZE(pll_regs); i++) {
@ -1141,8 +1139,23 @@ static void __init sun50i_h616_ccu_setup(struct device_node *node)
val |= BIT(24); val |= BIT(24);
writel(val, reg + SUN50I_H616_HDMI_CEC_CLK_REG); writel(val, reg + SUN50I_H616_HDMI_CEC_CLK_REG);
of_sunxi_ccu_probe(node, reg, &sun50i_h616_ccu_desc); return devm_sunxi_ccu_probe(&pdev->dev, reg, &sun50i_h616_ccu_desc);
} }
CLK_OF_DECLARE(sun50i_h616_ccu, "allwinner,sun50i-h616-ccu", static const struct of_device_id sun50i_h616_ccu_ids[] = {
sun50i_h616_ccu_setup); { .compatible = "allwinner,sun50i-h616-ccu" },
{ }
};
static struct platform_driver sun50i_h616_ccu_driver = {
.probe = sun50i_h616_ccu_probe,
.driver = {
.name = "sun50i-h616-ccu",
.suppress_bind_attrs = true,
.of_match_table = sun50i_h616_ccu_ids,
},
};
module_platform_driver(sun50i_h616_ccu_driver);
MODULE_IMPORT_NS(SUNXI_CCU);
MODULE_LICENSE("GPL");

View File

@ -9,7 +9,8 @@
#include <linux/clk-provider.h> #include <linux/clk-provider.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/of_address.h> #include <linux/module.h>
#include <linux/platform_device.h>
#include "ccu_common.h" #include "ccu_common.h"
#include "ccu_reset.h" #include "ccu_reset.h"
@ -1226,16 +1227,15 @@ static struct ccu_mux_nb sun6i_a31_cpu_nb = {
.bypass_index = 1, /* index of 24 MHz oscillator */ .bypass_index = 1, /* index of 24 MHz oscillator */
}; };
static void __init sun6i_a31_ccu_setup(struct device_node *node) static int sun6i_a31_ccu_probe(struct platform_device *pdev)
{ {
void __iomem *reg; void __iomem *reg;
int ret;
u32 val; u32 val;
reg = of_io_request_and_map(node, 0, of_node_full_name(node)); reg = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(reg)) { if (IS_ERR(reg))
pr_err("%pOF: Could not map the clock registers\n", node); return PTR_ERR(reg);
return;
}
/* Force the PLL-Audio-1x divider to 1 */ /* Force the PLL-Audio-1x divider to 1 */
val = readl(reg + SUN6I_A31_PLL_AUDIO_REG); val = readl(reg + SUN6I_A31_PLL_AUDIO_REG);
@ -1257,10 +1257,30 @@ static void __init sun6i_a31_ccu_setup(struct device_node *node)
val |= 0x3 << 12; val |= 0x3 << 12;
writel(val, reg + SUN6I_A31_AHB1_REG); writel(val, reg + SUN6I_A31_AHB1_REG);
of_sunxi_ccu_probe(node, reg, &sun6i_a31_ccu_desc); ret = devm_sunxi_ccu_probe(&pdev->dev, reg, &sun6i_a31_ccu_desc);
if (ret)
return ret;
ccu_mux_notifier_register(pll_cpu_clk.common.hw.clk, ccu_mux_notifier_register(pll_cpu_clk.common.hw.clk,
&sun6i_a31_cpu_nb); &sun6i_a31_cpu_nb);
return 0;
} }
CLK_OF_DECLARE(sun6i_a31_ccu, "allwinner,sun6i-a31-ccu",
sun6i_a31_ccu_setup); static const struct of_device_id sun6i_a31_ccu_ids[] = {
{ .compatible = "allwinner,sun6i-a31-ccu" },
{ }
};
static struct platform_driver sun6i_a31_ccu_driver = {
.probe = sun6i_a31_ccu_probe,
.driver = {
.name = "sun6i-a31-ccu",
.suppress_bind_attrs = true,
.of_match_table = sun6i_a31_ccu_ids,
},
};
module_platform_driver(sun6i_a31_ccu_driver);
MODULE_IMPORT_NS(SUNXI_CCU);
MODULE_LICENSE("GPL");

View File

@ -5,7 +5,8 @@
#include <linux/clk-provider.h> #include <linux/clk-provider.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/of_address.h> #include <linux/module.h>
#include <linux/platform_device.h>
#include "ccu_common.h" #include "ccu_common.h"
#include "ccu_reset.h" #include "ccu_reset.h"
@ -724,16 +725,14 @@ static const struct sunxi_ccu_desc sun8i_a23_ccu_desc = {
.num_resets = ARRAY_SIZE(sun8i_a23_ccu_resets), .num_resets = ARRAY_SIZE(sun8i_a23_ccu_resets),
}; };
static void __init sun8i_a23_ccu_setup(struct device_node *node) static int sun8i_a23_ccu_probe(struct platform_device *pdev)
{ {
void __iomem *reg; void __iomem *reg;
u32 val; u32 val;
reg = of_io_request_and_map(node, 0, of_node_full_name(node)); reg = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(reg)) { if (IS_ERR(reg))
pr_err("%pOF: Could not map the clock registers\n", node); return PTR_ERR(reg);
return;
}
/* Force the PLL-Audio-1x divider to 1 */ /* Force the PLL-Audio-1x divider to 1 */
val = readl(reg + SUN8I_A23_PLL_AUDIO_REG); val = readl(reg + SUN8I_A23_PLL_AUDIO_REG);
@ -745,7 +744,23 @@ static void __init sun8i_a23_ccu_setup(struct device_node *node)
val &= ~BIT(16); val &= ~BIT(16);
writel(val, reg + SUN8I_A23_PLL_MIPI_REG); writel(val, reg + SUN8I_A23_PLL_MIPI_REG);
of_sunxi_ccu_probe(node, reg, &sun8i_a23_ccu_desc); return devm_sunxi_ccu_probe(&pdev->dev, reg, &sun8i_a23_ccu_desc);
} }
CLK_OF_DECLARE(sun8i_a23_ccu, "allwinner,sun8i-a23-ccu",
sun8i_a23_ccu_setup); static const struct of_device_id sun8i_a23_ccu_ids[] = {
{ .compatible = "allwinner,sun8i-a23-ccu" },
{ }
};
static struct platform_driver sun8i_a23_ccu_driver = {
.probe = sun8i_a23_ccu_probe,
.driver = {
.name = "sun8i-a23-ccu",
.suppress_bind_attrs = true,
.of_match_table = sun8i_a23_ccu_ids,
},
};
module_platform_driver(sun8i_a23_ccu_driver);
MODULE_IMPORT_NS(SUNXI_CCU);
MODULE_LICENSE("GPL");

View File

@ -5,7 +5,8 @@
#include <linux/clk-provider.h> #include <linux/clk-provider.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/of_address.h> #include <linux/module.h>
#include <linux/platform_device.h>
#include "ccu_common.h" #include "ccu_common.h"
#include "ccu_reset.h" #include "ccu_reset.h"
@ -784,16 +785,15 @@ static struct ccu_mux_nb sun8i_a33_cpu_nb = {
.bypass_index = 1, /* index of 24 MHz oscillator */ .bypass_index = 1, /* index of 24 MHz oscillator */
}; };
static void __init sun8i_a33_ccu_setup(struct device_node *node) static int sun8i_a33_ccu_probe(struct platform_device *pdev)
{ {
void __iomem *reg; void __iomem *reg;
int ret;
u32 val; u32 val;
reg = of_io_request_and_map(node, 0, of_node_full_name(node)); reg = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(reg)) { if (IS_ERR(reg))
pr_err("%pOF: Could not map the clock registers\n", node); return PTR_ERR(reg);
return;
}
/* Force the PLL-Audio-1x divider to 1 */ /* Force the PLL-Audio-1x divider to 1 */
val = readl(reg + SUN8I_A33_PLL_AUDIO_REG); val = readl(reg + SUN8I_A33_PLL_AUDIO_REG);
@ -805,7 +805,9 @@ static void __init sun8i_a33_ccu_setup(struct device_node *node)
val &= ~BIT(16); val &= ~BIT(16);
writel(val, reg + SUN8I_A33_PLL_MIPI_REG); writel(val, reg + SUN8I_A33_PLL_MIPI_REG);
of_sunxi_ccu_probe(node, reg, &sun8i_a33_ccu_desc); ret = devm_sunxi_ccu_probe(&pdev->dev, reg, &sun8i_a33_ccu_desc);
if (ret)
return ret;
/* Gate then ungate PLL CPU after any rate changes */ /* Gate then ungate PLL CPU after any rate changes */
ccu_pll_notifier_register(&sun8i_a33_pll_cpu_nb); ccu_pll_notifier_register(&sun8i_a33_pll_cpu_nb);
@ -813,6 +815,24 @@ static void __init sun8i_a33_ccu_setup(struct device_node *node)
/* Reparent CPU during PLL CPU rate changes */ /* Reparent CPU during PLL CPU rate changes */
ccu_mux_notifier_register(pll_cpux_clk.common.hw.clk, ccu_mux_notifier_register(pll_cpux_clk.common.hw.clk,
&sun8i_a33_cpu_nb); &sun8i_a33_cpu_nb);
return 0;
} }
CLK_OF_DECLARE(sun8i_a33_ccu, "allwinner,sun8i-a33-ccu",
sun8i_a33_ccu_setup); static const struct of_device_id sun8i_a33_ccu_ids[] = {
{ .compatible = "allwinner,sun8i-a33-ccu" },
{ }
};
static struct platform_driver sun8i_a33_ccu_driver = {
.probe = sun8i_a33_ccu_probe,
.driver = {
.name = "sun8i-a33-ccu",
.suppress_bind_attrs = true,
.of_match_table = sun8i_a33_ccu_ids,
},
};
module_platform_driver(sun8i_a33_ccu_driver);
MODULE_IMPORT_NS(SUNXI_CCU);
MODULE_LICENSE("GPL");

View File

@ -5,7 +5,7 @@
#include <linux/clk-provider.h> #include <linux/clk-provider.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/of_address.h> #include <linux/module.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include "ccu_common.h" #include "ccu_common.h"
@ -920,4 +920,7 @@ static struct platform_driver sun8i_a83t_ccu_driver = {
.of_match_table = sun8i_a83t_ccu_ids, .of_match_table = sun8i_a83t_ccu_ids,
}, },
}; };
builtin_platform_driver(sun8i_a83t_ccu_driver); module_platform_driver(sun8i_a83t_ccu_driver);
MODULE_IMPORT_NS(SUNXI_CCU);
MODULE_LICENSE("GPL");

View File

@ -5,8 +5,8 @@
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/clk-provider.h> #include <linux/clk-provider.h>
#include <linux/of_address.h> #include <linux/module.h>
#include <linux/of_platform.h> #include <linux/of_device.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/reset.h> #include <linux/reset.h>
@ -394,4 +394,7 @@ static struct platform_driver sunxi_de2_clk_driver = {
.of_match_table = sunxi_de2_clk_ids, .of_match_table = sunxi_de2_clk_ids,
}, },
}; };
builtin_platform_driver(sunxi_de2_clk_driver); module_platform_driver(sunxi_de2_clk_driver);
MODULE_IMPORT_NS(SUNXI_CCU);
MODULE_LICENSE("GPL");

View File

@ -5,7 +5,9 @@
#include <linux/clk-provider.h> #include <linux/clk-provider.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/of_address.h> #include <linux/module.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include "ccu_common.h" #include "ccu_common.h"
#include "ccu_reset.h" #include "ccu_reset.h"
@ -1137,24 +1139,29 @@ static struct ccu_mux_nb sun8i_h3_cpu_nb = {
.bypass_index = 1, /* index of 24 MHz oscillator */ .bypass_index = 1, /* index of 24 MHz oscillator */
}; };
static void __init sunxi_h3_h5_ccu_init(struct device_node *node, static int sun8i_h3_ccu_probe(struct platform_device *pdev)
const struct sunxi_ccu_desc *desc)
{ {
const struct sunxi_ccu_desc *desc;
void __iomem *reg; void __iomem *reg;
int ret;
u32 val; u32 val;
reg = of_io_request_and_map(node, 0, of_node_full_name(node)); desc = of_device_get_match_data(&pdev->dev);
if (IS_ERR(reg)) { if (!desc)
pr_err("%pOF: Could not map the clock registers\n", node); return -EINVAL;
return;
} reg = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(reg))
return PTR_ERR(reg);
/* Force the PLL-Audio-1x divider to 1 */ /* Force the PLL-Audio-1x divider to 1 */
val = readl(reg + SUN8I_H3_PLL_AUDIO_REG); val = readl(reg + SUN8I_H3_PLL_AUDIO_REG);
val &= ~GENMASK(19, 16); val &= ~GENMASK(19, 16);
writel(val | (0 << 16), reg + SUN8I_H3_PLL_AUDIO_REG); writel(val | (0 << 16), reg + SUN8I_H3_PLL_AUDIO_REG);
of_sunxi_ccu_probe(node, reg, desc); ret = devm_sunxi_ccu_probe(&pdev->dev, reg, desc);
if (ret)
return ret;
/* Gate then ungate PLL CPU after any rate changes */ /* Gate then ungate PLL CPU after any rate changes */
ccu_pll_notifier_register(&sun8i_h3_pll_cpu_nb); ccu_pll_notifier_register(&sun8i_h3_pll_cpu_nb);
@ -1162,18 +1169,31 @@ static void __init sunxi_h3_h5_ccu_init(struct device_node *node,
/* Reparent CPU during PLL CPU rate changes */ /* Reparent CPU during PLL CPU rate changes */
ccu_mux_notifier_register(pll_cpux_clk.common.hw.clk, ccu_mux_notifier_register(pll_cpux_clk.common.hw.clk,
&sun8i_h3_cpu_nb); &sun8i_h3_cpu_nb);
return 0;
} }
static void __init sun8i_h3_ccu_setup(struct device_node *node) static const struct of_device_id sun8i_h3_ccu_ids[] = {
{ {
sunxi_h3_h5_ccu_init(node, &sun8i_h3_ccu_desc); .compatible = "allwinner,sun8i-h3-ccu",
} .data = &sun8i_h3_ccu_desc,
CLK_OF_DECLARE(sun8i_h3_ccu, "allwinner,sun8i-h3-ccu", },
sun8i_h3_ccu_setup); {
.compatible = "allwinner,sun50i-h5-ccu",
.data = &sun50i_h5_ccu_desc,
},
{ }
};
static void __init sun50i_h5_ccu_setup(struct device_node *node) static struct platform_driver sun8i_h3_ccu_driver = {
{ .probe = sun8i_h3_ccu_probe,
sunxi_h3_h5_ccu_init(node, &sun50i_h5_ccu_desc); .driver = {
} .name = "sun8i-h3-ccu",
CLK_OF_DECLARE(sun50i_h5_ccu, "allwinner,sun50i-h5-ccu", .suppress_bind_attrs = true,
sun50i_h5_ccu_setup); .of_match_table = sun8i_h3_ccu_ids,
},
};
module_platform_driver(sun8i_h3_ccu_driver);
MODULE_IMPORT_NS(SUNXI_CCU);
MODULE_LICENSE("GPL");

View File

@ -4,7 +4,8 @@
*/ */
#include <linux/clk-provider.h> #include <linux/clk-provider.h>
#include <linux/of_address.h> #include <linux/module.h>
#include <linux/of_device.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include "ccu_common.h" #include "ccu_common.h"
@ -254,37 +255,47 @@ static const struct sunxi_ccu_desc sun50i_a64_r_ccu_desc = {
.num_resets = ARRAY_SIZE(sun50i_a64_r_ccu_resets), .num_resets = ARRAY_SIZE(sun50i_a64_r_ccu_resets),
}; };
static void __init sunxi_r_ccu_init(struct device_node *node, static int sun8i_r_ccu_probe(struct platform_device *pdev)
const struct sunxi_ccu_desc *desc)
{ {
const struct sunxi_ccu_desc *desc;
void __iomem *reg; void __iomem *reg;
reg = of_io_request_and_map(node, 0, of_node_full_name(node)); desc = of_device_get_match_data(&pdev->dev);
if (IS_ERR(reg)) { if (!desc)
pr_err("%pOF: Could not map the clock registers\n", node); return -EINVAL;
return;
}
of_sunxi_ccu_probe(node, reg, desc); reg = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(reg))
return PTR_ERR(reg);
return devm_sunxi_ccu_probe(&pdev->dev, reg, desc);
} }
static void __init sun8i_a83t_r_ccu_setup(struct device_node *node) static const struct of_device_id sun8i_r_ccu_ids[] = {
{ {
sunxi_r_ccu_init(node, &sun8i_a83t_r_ccu_desc); .compatible = "allwinner,sun8i-a83t-r-ccu",
} .data = &sun8i_a83t_r_ccu_desc,
CLK_OF_DECLARE(sun8i_a83t_r_ccu, "allwinner,sun8i-a83t-r-ccu", },
sun8i_a83t_r_ccu_setup); {
.compatible = "allwinner,sun8i-h3-r-ccu",
.data = &sun8i_h3_r_ccu_desc,
},
{
.compatible = "allwinner,sun50i-a64-r-ccu",
.data = &sun50i_a64_r_ccu_desc,
},
{ }
};
static void __init sun8i_h3_r_ccu_setup(struct device_node *node) static struct platform_driver sun8i_r_ccu_driver = {
{ .probe = sun8i_r_ccu_probe,
sunxi_r_ccu_init(node, &sun8i_h3_r_ccu_desc); .driver = {
} .name = "sun8i-r-ccu",
CLK_OF_DECLARE(sun8i_h3_r_ccu, "allwinner,sun8i-h3-r-ccu", .suppress_bind_attrs = true,
sun8i_h3_r_ccu_setup); .of_match_table = sun8i_r_ccu_ids,
},
};
module_platform_driver(sun8i_r_ccu_driver);
static void __init sun50i_a64_r_ccu_setup(struct device_node *node) MODULE_IMPORT_NS(SUNXI_CCU);
{ MODULE_LICENSE("GPL");
sunxi_r_ccu_init(node, &sun50i_a64_r_ccu_desc);
}
CLK_OF_DECLARE(sun50i_a64_r_ccu, "allwinner,sun50i-a64-r-ccu",
sun50i_a64_r_ccu_setup);

View File

@ -5,6 +5,7 @@
#include <linux/clk-provider.h> #include <linux/clk-provider.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/module.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/regmap.h> #include <linux/regmap.h>
@ -1371,4 +1372,7 @@ static struct platform_driver sun8i_r40_ccu_driver = {
.of_match_table = sun8i_r40_ccu_ids, .of_match_table = sun8i_r40_ccu_ids,
}, },
}; };
builtin_platform_driver(sun8i_r40_ccu_driver); module_platform_driver(sun8i_r40_ccu_driver);
MODULE_IMPORT_NS(SUNXI_CCU);
MODULE_LICENSE("GPL");

View File

@ -8,7 +8,9 @@
#include <linux/clk-provider.h> #include <linux/clk-provider.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/of_address.h> #include <linux/module.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include "ccu_common.h" #include "ccu_common.h"
#include "ccu_reset.h" #include "ccu_reset.h"
@ -805,38 +807,49 @@ static const struct sunxi_ccu_desc sun8i_v3_ccu_desc = {
.num_resets = ARRAY_SIZE(sun8i_v3_ccu_resets), .num_resets = ARRAY_SIZE(sun8i_v3_ccu_resets),
}; };
static void __init sun8i_v3_v3s_ccu_init(struct device_node *node, static int sun8i_v3s_ccu_probe(struct platform_device *pdev)
const struct sunxi_ccu_desc *ccu_desc)
{ {
const struct sunxi_ccu_desc *desc;
void __iomem *reg; void __iomem *reg;
u32 val; u32 val;
reg = of_io_request_and_map(node, 0, of_node_full_name(node)); desc = of_device_get_match_data(&pdev->dev);
if (IS_ERR(reg)) { if (!desc)
pr_err("%pOF: Could not map the clock registers\n", node); return -EINVAL;
return;
} reg = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(reg))
return PTR_ERR(reg);
/* Force the PLL-Audio-1x divider to 1 */ /* Force the PLL-Audio-1x divider to 1 */
val = readl(reg + SUN8I_V3S_PLL_AUDIO_REG); val = readl(reg + SUN8I_V3S_PLL_AUDIO_REG);
val &= ~GENMASK(19, 16); val &= ~GENMASK(19, 16);
writel(val, reg + SUN8I_V3S_PLL_AUDIO_REG); writel(val, reg + SUN8I_V3S_PLL_AUDIO_REG);
of_sunxi_ccu_probe(node, reg, ccu_desc); return devm_sunxi_ccu_probe(&pdev->dev, reg, desc);
} }
static void __init sun8i_v3s_ccu_setup(struct device_node *node) static const struct of_device_id sun8i_v3s_ccu_ids[] = {
{ {
sun8i_v3_v3s_ccu_init(node, &sun8i_v3s_ccu_desc); .compatible = "allwinner,sun8i-v3-ccu",
} .data = &sun8i_v3_ccu_desc,
},
{
.compatible = "allwinner,sun8i-v3s-ccu",
.data = &sun8i_v3s_ccu_desc,
},
{ }
};
static void __init sun8i_v3_ccu_setup(struct device_node *node) static struct platform_driver sun8i_v3s_ccu_driver = {
{ .probe = sun8i_v3s_ccu_probe,
sun8i_v3_v3s_ccu_init(node, &sun8i_v3_ccu_desc); .driver = {
} .name = "sun8i-v3s-ccu",
.suppress_bind_attrs = true,
.of_match_table = sun8i_v3s_ccu_ids,
},
};
module_platform_driver(sun8i_v3s_ccu_driver);
CLK_OF_DECLARE(sun8i_v3s_ccu, "allwinner,sun8i-v3s-ccu", MODULE_IMPORT_NS(SUNXI_CCU);
sun8i_v3s_ccu_setup); MODULE_LICENSE("GPL");
CLK_OF_DECLARE(sun8i_v3_ccu, "allwinner,sun8i-v3-ccu",
sun8i_v3_ccu_setup);

View File

@ -5,7 +5,7 @@
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/clk-provider.h> #include <linux/clk-provider.h>
#include <linux/of_address.h> #include <linux/module.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/reset.h> #include <linux/reset.h>
@ -270,4 +270,7 @@ static struct platform_driver sun9i_a80_de_clk_driver = {
.of_match_table = sun9i_a80_de_clk_ids, .of_match_table = sun9i_a80_de_clk_ids,
}, },
}; };
builtin_platform_driver(sun9i_a80_de_clk_driver); module_platform_driver(sun9i_a80_de_clk_driver);
MODULE_IMPORT_NS(SUNXI_CCU);
MODULE_LICENSE("GPL");

View File

@ -5,7 +5,7 @@
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/clk-provider.h> #include <linux/clk-provider.h>
#include <linux/of_address.h> #include <linux/module.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include "ccu_common.h" #include "ccu_common.h"
@ -138,4 +138,7 @@ static struct platform_driver sun9i_a80_usb_clk_driver = {
.of_match_table = sun9i_a80_usb_clk_ids, .of_match_table = sun9i_a80_usb_clk_ids,
}, },
}; };
builtin_platform_driver(sun9i_a80_usb_clk_driver); module_platform_driver(sun9i_a80_usb_clk_driver);
MODULE_IMPORT_NS(SUNXI_CCU);
MODULE_LICENSE("GPL");

View File

@ -5,7 +5,7 @@
#include <linux/clk-provider.h> #include <linux/clk-provider.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/of_address.h> #include <linux/module.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include "ccu_common.h" #include "ccu_common.h"
@ -1245,4 +1245,7 @@ static struct platform_driver sun9i_a80_ccu_driver = {
.of_match_table = sun9i_a80_ccu_ids, .of_match_table = sun9i_a80_ccu_ids,
}, },
}; };
builtin_platform_driver(sun9i_a80_ccu_driver); module_platform_driver(sun9i_a80_ccu_driver);
MODULE_IMPORT_NS(SUNXI_CCU);
MODULE_LICENSE("GPL");

View File

@ -6,7 +6,8 @@
#include <linux/clk-provider.h> #include <linux/clk-provider.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/of_address.h> #include <linux/module.h>
#include <linux/platform_device.h>
#include "ccu_common.h" #include "ccu_common.h"
#include "ccu_reset.h" #include "ccu_reset.h"
@ -522,23 +523,24 @@ static struct ccu_mux_nb suniv_cpu_nb = {
.bypass_index = 1, /* index of 24 MHz oscillator */ .bypass_index = 1, /* index of 24 MHz oscillator */
}; };
static void __init suniv_f1c100s_ccu_setup(struct device_node *node) static int suniv_f1c100s_ccu_probe(struct platform_device *pdev)
{ {
void __iomem *reg; void __iomem *reg;
int ret;
u32 val; u32 val;
reg = of_io_request_and_map(node, 0, of_node_full_name(node)); reg = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(reg)) { if (IS_ERR(reg))
pr_err("%pOF: Could not map the clock registers\n", node); return PTR_ERR(reg);
return;
}
/* Force the PLL-Audio-1x divider to 4 */ /* Force the PLL-Audio-1x divider to 4 */
val = readl(reg + SUNIV_PLL_AUDIO_REG); val = readl(reg + SUNIV_PLL_AUDIO_REG);
val &= ~GENMASK(19, 16); val &= ~GENMASK(19, 16);
writel(val | (3 << 16), reg + SUNIV_PLL_AUDIO_REG); writel(val | (3 << 16), reg + SUNIV_PLL_AUDIO_REG);
of_sunxi_ccu_probe(node, reg, &suniv_ccu_desc); ret = devm_sunxi_ccu_probe(&pdev->dev, reg, &suniv_ccu_desc);
if (ret)
return ret;
/* Gate then ungate PLL CPU after any rate changes */ /* Gate then ungate PLL CPU after any rate changes */
ccu_pll_notifier_register(&suniv_pll_cpu_nb); ccu_pll_notifier_register(&suniv_pll_cpu_nb);
@ -546,6 +548,24 @@ static void __init suniv_f1c100s_ccu_setup(struct device_node *node)
/* Reparent CPU during PLL CPU rate changes */ /* Reparent CPU during PLL CPU rate changes */
ccu_mux_notifier_register(pll_cpu_clk.common.hw.clk, ccu_mux_notifier_register(pll_cpu_clk.common.hw.clk,
&suniv_cpu_nb); &suniv_cpu_nb);
return 0;
} }
CLK_OF_DECLARE(suniv_f1c100s_ccu, "allwinner,suniv-f1c100s-ccu",
suniv_f1c100s_ccu_setup); static const struct of_device_id suniv_f1c100s_ccu_ids[] = {
{ .compatible = "allwinner,suniv-f1c100s-ccu" },
{ }
};
static struct platform_driver suniv_f1c100s_ccu_driver = {
.probe = suniv_f1c100s_ccu_probe,
.driver = {
.name = "suniv-f1c100s-ccu",
.suppress_bind_attrs = true,
.of_match_table = suniv_f1c100s_ccu_ids,
},
};
module_platform_driver(suniv_f1c100s_ccu_driver);
MODULE_IMPORT_NS(SUNXI_CCU);
MODULE_LICENSE("GPL");

View File

@ -9,6 +9,7 @@
#include <linux/clk-provider.h> #include <linux/clk-provider.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/iopoll.h> #include <linux/iopoll.h>
#include <linux/module.h>
#include <linux/slab.h> #include <linux/slab.h>
#include "ccu_common.h" #include "ccu_common.h"
@ -36,6 +37,7 @@ void ccu_helper_wait_for_lock(struct ccu_common *common, u32 lock)
WARN_ON(readl_relaxed_poll_timeout(addr, reg, reg & lock, 100, 70000)); WARN_ON(readl_relaxed_poll_timeout(addr, reg, reg & lock, 100, 70000));
} }
EXPORT_SYMBOL_NS_GPL(ccu_helper_wait_for_lock, SUNXI_CCU);
/* /*
* This clock notifier is called when the frequency of a PLL clock is * This clock notifier is called when the frequency of a PLL clock is
@ -83,6 +85,7 @@ int ccu_pll_notifier_register(struct ccu_pll_nb *pll_nb)
return clk_notifier_register(pll_nb->common->hw.clk, return clk_notifier_register(pll_nb->common->hw.clk,
&pll_nb->clk_nb); &pll_nb->clk_nb);
} }
EXPORT_SYMBOL_NS_GPL(ccu_pll_notifier_register, SUNXI_CCU);
static int sunxi_ccu_probe(struct sunxi_ccu *ccu, struct device *dev, static int sunxi_ccu_probe(struct sunxi_ccu *ccu, struct device *dev,
struct device_node *node, void __iomem *reg, struct device_node *node, void __iomem *reg,
@ -194,6 +197,7 @@ int devm_sunxi_ccu_probe(struct device *dev, void __iomem *reg,
return 0; return 0;
} }
EXPORT_SYMBOL_NS_GPL(devm_sunxi_ccu_probe, SUNXI_CCU);
void of_sunxi_ccu_probe(struct device_node *node, void __iomem *reg, void of_sunxi_ccu_probe(struct device_node *node, void __iomem *reg,
const struct sunxi_ccu_desc *desc) const struct sunxi_ccu_desc *desc)
@ -211,3 +215,5 @@ void of_sunxi_ccu_probe(struct device_node *node, void __iomem *reg,
kfree(ccu); kfree(ccu);
} }
} }
MODULE_LICENSE("GPL");

View File

@ -141,3 +141,4 @@ const struct clk_ops ccu_div_ops = {
.recalc_rate = ccu_div_recalc_rate, .recalc_rate = ccu_div_recalc_rate,
.set_rate = ccu_div_set_rate, .set_rate = ccu_div_set_rate,
}; };
EXPORT_SYMBOL_NS_GPL(ccu_div_ops, SUNXI_CCU);

View File

@ -108,6 +108,22 @@ struct ccu_div {
_shift, _width, _table, 0, \ _shift, _width, _table, 0, \
_flags) _flags)
#define SUNXI_CCU_DIV_TABLE_HW(_struct, _name, _parent, _reg, \
_shift, _width, \
_table, _flags) \
struct ccu_div _struct = { \
.div = _SUNXI_CCU_DIV_TABLE(_shift, _width, \
_table), \
.common = { \
.reg = _reg, \
.hw.init = CLK_HW_INIT_HW(_name, \
_parent, \
&ccu_div_ops, \
_flags), \
} \
}
#define SUNXI_CCU_M_WITH_MUX_TABLE_GATE(_struct, _name, \ #define SUNXI_CCU_M_WITH_MUX_TABLE_GATE(_struct, _name, \
_parents, _table, \ _parents, _table, \
_reg, \ _reg, \
@ -166,6 +182,68 @@ struct ccu_div {
SUNXI_CCU_M_WITH_GATE(_struct, _name, _parent, _reg, \ SUNXI_CCU_M_WITH_GATE(_struct, _name, _parent, _reg, \
_mshift, _mwidth, 0, _flags) _mshift, _mwidth, 0, _flags)
#define SUNXI_CCU_M_DATA_WITH_MUX_GATE(_struct, _name, _parents, _reg, \
_mshift, _mwidth, \
_muxshift, _muxwidth, \
_gate, _flags) \
struct ccu_div _struct = { \
.enable = _gate, \
.div = _SUNXI_CCU_DIV(_mshift, _mwidth), \
.mux = _SUNXI_CCU_MUX(_muxshift, _muxwidth), \
.common = { \
.reg = _reg, \
.hw.init = CLK_HW_INIT_PARENTS_DATA(_name, \
_parents, \
&ccu_div_ops, \
_flags), \
}, \
}
#define SUNXI_CCU_M_DATA_WITH_MUX(_struct, _name, _parents, _reg, \
_mshift, _mwidth, \
_muxshift, _muxwidth, \
_flags) \
SUNXI_CCU_M_DATA_WITH_MUX_GATE(_struct, _name, _parents, _reg, \
_mshift, _mwidth, \
_muxshift, _muxwidth, \
0, _flags)
#define SUNXI_CCU_M_HW_WITH_MUX_GATE(_struct, _name, _parents, _reg, \
_mshift, _mwidth, _muxshift, _muxwidth, \
_gate, _flags) \
struct ccu_div _struct = { \
.enable = _gate, \
.div = _SUNXI_CCU_DIV(_mshift, _mwidth), \
.mux = _SUNXI_CCU_MUX(_muxshift, _muxwidth), \
.common = { \
.reg = _reg, \
.hw.init = CLK_HW_INIT_PARENTS_HW(_name, \
_parents, \
&ccu_div_ops, \
_flags), \
}, \
}
#define SUNXI_CCU_M_HWS_WITH_GATE(_struct, _name, _parent, _reg, \
_mshift, _mwidth, _gate, \
_flags) \
struct ccu_div _struct = { \
.enable = _gate, \
.div = _SUNXI_CCU_DIV(_mshift, _mwidth), \
.common = { \
.reg = _reg, \
.hw.init = CLK_HW_INIT_HWS(_name, \
_parent, \
&ccu_div_ops, \
_flags), \
}, \
}
#define SUNXI_CCU_M_HWS(_struct, _name, _parent, _reg, _mshift, \
_mwidth, _flags) \
SUNXI_CCU_M_HWS_WITH_GATE(_struct, _name, _parent, _reg, \
_mshift, _mwidth, 0, _flags)
static inline struct ccu_div *hw_to_ccu_div(struct clk_hw *hw) static inline struct ccu_div *hw_to_ccu_div(struct clk_hw *hw)
{ {
struct ccu_common *common = hw_to_ccu_common(hw); struct ccu_common *common = hw_to_ccu_common(hw);

View File

@ -18,6 +18,7 @@ bool ccu_frac_helper_is_enabled(struct ccu_common *common,
return !(readl(common->base + common->reg) & cf->enable); return !(readl(common->base + common->reg) & cf->enable);
} }
EXPORT_SYMBOL_NS_GPL(ccu_frac_helper_is_enabled, SUNXI_CCU);
void ccu_frac_helper_enable(struct ccu_common *common, void ccu_frac_helper_enable(struct ccu_common *common,
struct ccu_frac_internal *cf) struct ccu_frac_internal *cf)
@ -33,6 +34,7 @@ void ccu_frac_helper_enable(struct ccu_common *common,
writel(reg & ~cf->enable, common->base + common->reg); writel(reg & ~cf->enable, common->base + common->reg);
spin_unlock_irqrestore(common->lock, flags); spin_unlock_irqrestore(common->lock, flags);
} }
EXPORT_SYMBOL_NS_GPL(ccu_frac_helper_enable, SUNXI_CCU);
void ccu_frac_helper_disable(struct ccu_common *common, void ccu_frac_helper_disable(struct ccu_common *common,
struct ccu_frac_internal *cf) struct ccu_frac_internal *cf)
@ -48,6 +50,7 @@ void ccu_frac_helper_disable(struct ccu_common *common,
writel(reg | cf->enable, common->base + common->reg); writel(reg | cf->enable, common->base + common->reg);
spin_unlock_irqrestore(common->lock, flags); spin_unlock_irqrestore(common->lock, flags);
} }
EXPORT_SYMBOL_NS_GPL(ccu_frac_helper_disable, SUNXI_CCU);
bool ccu_frac_helper_has_rate(struct ccu_common *common, bool ccu_frac_helper_has_rate(struct ccu_common *common,
struct ccu_frac_internal *cf, struct ccu_frac_internal *cf,
@ -58,6 +61,7 @@ bool ccu_frac_helper_has_rate(struct ccu_common *common,
return (cf->rates[0] == rate) || (cf->rates[1] == rate); return (cf->rates[0] == rate) || (cf->rates[1] == rate);
} }
EXPORT_SYMBOL_NS_GPL(ccu_frac_helper_has_rate, SUNXI_CCU);
unsigned long ccu_frac_helper_read_rate(struct ccu_common *common, unsigned long ccu_frac_helper_read_rate(struct ccu_common *common,
struct ccu_frac_internal *cf) struct ccu_frac_internal *cf)
@ -79,6 +83,7 @@ unsigned long ccu_frac_helper_read_rate(struct ccu_common *common,
return (reg & cf->select) ? cf->rates[1] : cf->rates[0]; return (reg & cf->select) ? cf->rates[1] : cf->rates[0];
} }
EXPORT_SYMBOL_NS_GPL(ccu_frac_helper_read_rate, SUNXI_CCU);
int ccu_frac_helper_set_rate(struct ccu_common *common, int ccu_frac_helper_set_rate(struct ccu_common *common,
struct ccu_frac_internal *cf, struct ccu_frac_internal *cf,
@ -107,3 +112,4 @@ int ccu_frac_helper_set_rate(struct ccu_common *common,
return 0; return 0;
} }
EXPORT_SYMBOL_NS_GPL(ccu_frac_helper_set_rate, SUNXI_CCU);

View File

@ -24,6 +24,7 @@ void ccu_gate_helper_disable(struct ccu_common *common, u32 gate)
spin_unlock_irqrestore(common->lock, flags); spin_unlock_irqrestore(common->lock, flags);
} }
EXPORT_SYMBOL_NS_GPL(ccu_gate_helper_disable, SUNXI_CCU);
static void ccu_gate_disable(struct clk_hw *hw) static void ccu_gate_disable(struct clk_hw *hw)
{ {
@ -49,6 +50,7 @@ int ccu_gate_helper_enable(struct ccu_common *common, u32 gate)
return 0; return 0;
} }
EXPORT_SYMBOL_NS_GPL(ccu_gate_helper_enable, SUNXI_CCU);
static int ccu_gate_enable(struct clk_hw *hw) static int ccu_gate_enable(struct clk_hw *hw)
{ {
@ -64,6 +66,7 @@ int ccu_gate_helper_is_enabled(struct ccu_common *common, u32 gate)
return readl(common->base + common->reg) & gate; return readl(common->base + common->reg) & gate;
} }
EXPORT_SYMBOL_NS_GPL(ccu_gate_helper_is_enabled, SUNXI_CCU);
static int ccu_gate_is_enabled(struct clk_hw *hw) static int ccu_gate_is_enabled(struct clk_hw *hw)
{ {
@ -124,3 +127,4 @@ const struct clk_ops ccu_gate_ops = {
.set_rate = ccu_gate_set_rate, .set_rate = ccu_gate_set_rate,
.recalc_rate = ccu_gate_recalc_rate, .recalc_rate = ccu_gate_recalc_rate,
}; };
EXPORT_SYMBOL_NS_GPL(ccu_gate_ops, SUNXI_CCU);

View File

@ -53,7 +53,7 @@ struct ccu_gate {
} }
/* /*
* The following two macros allow the re-use of the data structure * The following macros allow the re-use of the data structure
* holding the parent info. * holding the parent info.
*/ */
#define SUNXI_CCU_GATE_HWS(_struct, _name, _parent, _reg, _gate, _flags) \ #define SUNXI_CCU_GATE_HWS(_struct, _name, _parent, _reg, _gate, _flags) \
@ -68,6 +68,21 @@ struct ccu_gate {
} \ } \
} }
#define SUNXI_CCU_GATE_HWS_WITH_PREDIV(_struct, _name, _parent, _reg, \
_gate, _prediv, _flags) \
struct ccu_gate _struct = { \
.enable = _gate, \
.common = { \
.reg = _reg, \
.prediv = _prediv, \
.features = CCU_FEATURE_ALL_PREDIV, \
.hw.init = CLK_HW_INIT_HWS(_name, \
_parent, \
&ccu_gate_ops, \
_flags), \
} \
}
#define SUNXI_CCU_GATE_DATA(_struct, _name, _data, _reg, _gate, _flags) \ #define SUNXI_CCU_GATE_DATA(_struct, _name, _data, _reg, _gate, _flags) \
struct ccu_gate _struct = { \ struct ccu_gate _struct = { \
.enable = _gate, \ .enable = _gate, \
@ -81,6 +96,21 @@ struct ccu_gate {
} \ } \
} }
#define SUNXI_CCU_GATE_DATA_WITH_PREDIV(_struct, _name, _parent, _reg, \
_gate, _prediv, _flags) \
struct ccu_gate _struct = { \
.enable = _gate, \
.common = { \
.reg = _reg, \
.prediv = _prediv, \
.features = CCU_FEATURE_ALL_PREDIV, \
.hw.init = CLK_HW_INIT_PARENTS_DATA(_name, \
_parent, \
&ccu_gate_ops, \
_flags), \
} \
}
static inline struct ccu_gate *hw_to_ccu_gate(struct clk_hw *hw) static inline struct ccu_gate *hw_to_ccu_gate(struct clk_hw *hw)
{ {
struct ccu_common *common = hw_to_ccu_common(hw); struct ccu_common *common = hw_to_ccu_common(hw);

View File

@ -245,6 +245,7 @@ const struct clk_ops ccu_mp_ops = {
.recalc_rate = ccu_mp_recalc_rate, .recalc_rate = ccu_mp_recalc_rate,
.set_rate = ccu_mp_set_rate, .set_rate = ccu_mp_set_rate,
}; };
EXPORT_SYMBOL_NS_GPL(ccu_mp_ops, SUNXI_CCU);
/* /*
* Support for MMC timing mode switching * Support for MMC timing mode switching
@ -325,3 +326,4 @@ const struct clk_ops ccu_mp_mmc_ops = {
.recalc_rate = ccu_mp_mmc_recalc_rate, .recalc_rate = ccu_mp_mmc_recalc_rate,
.set_rate = ccu_mp_mmc_set_rate, .set_rate = ccu_mp_mmc_set_rate,
}; };
EXPORT_SYMBOL_NS_GPL(ccu_mp_mmc_ops, SUNXI_CCU);

View File

@ -82,6 +82,55 @@ struct ccu_mp {
_muxshift, _muxwidth, \ _muxshift, _muxwidth, \
0, _flags) 0, _flags)
#define SUNXI_CCU_MP_DATA_WITH_MUX_GATE(_struct, _name, _parents, _reg, \
_mshift, _mwidth, \
_pshift, _pwidth, \
_muxshift, _muxwidth, \
_gate, _flags) \
struct ccu_mp _struct = { \
.enable = _gate, \
.m = _SUNXI_CCU_DIV(_mshift, _mwidth), \
.p = _SUNXI_CCU_DIV(_pshift, _pwidth), \
.mux = _SUNXI_CCU_MUX(_muxshift, _muxwidth), \
.common = { \
.reg = _reg, \
.hw.init = CLK_HW_INIT_PARENTS_DATA(_name, \
_parents, \
&ccu_mp_ops, \
_flags), \
} \
}
#define SUNXI_CCU_MP_DATA_WITH_MUX(_struct, _name, _parents, _reg, \
_mshift, _mwidth, \
_pshift, _pwidth, \
_muxshift, _muxwidth, \
_flags) \
SUNXI_CCU_MP_DATA_WITH_MUX_GATE(_struct, _name, _parents, _reg, \
_mshift, _mwidth, \
_pshift, _pwidth, \
_muxshift, _muxwidth, \
0, _flags)
#define SUNXI_CCU_MP_HW_WITH_MUX_GATE(_struct, _name, _parents, _reg, \
_mshift, _mwidth, \
_pshift, _pwidth, \
_muxshift, _muxwidth, \
_gate, _flags) \
struct ccu_mp _struct = { \
.enable = _gate, \
.m = _SUNXI_CCU_DIV(_mshift, _mwidth), \
.p = _SUNXI_CCU_DIV(_pshift, _pwidth), \
.mux = _SUNXI_CCU_MUX(_muxshift, _muxwidth), \
.common = { \
.reg = _reg, \
.hw.init = CLK_HW_INIT_PARENTS_HW(_name, \
_parents, \
&ccu_mp_ops, \
_flags), \
} \
}
static inline struct ccu_mp *hw_to_ccu_mp(struct clk_hw *hw) static inline struct ccu_mp *hw_to_ccu_mp(struct clk_hw *hw)
{ {
struct ccu_common *common = hw_to_ccu_common(hw); struct ccu_common *common = hw_to_ccu_common(hw);

View File

@ -170,3 +170,4 @@ const struct clk_ops ccu_mult_ops = {
.recalc_rate = ccu_mult_recalc_rate, .recalc_rate = ccu_mult_recalc_rate,
.set_rate = ccu_mult_set_rate, .set_rate = ccu_mult_set_rate,
}; };
EXPORT_SYMBOL_NS_GPL(ccu_mult_ops, SUNXI_CCU);

View File

@ -64,6 +64,7 @@ unsigned long ccu_mux_helper_apply_prediv(struct ccu_common *common,
{ {
return parent_rate / ccu_mux_get_prediv(common, cm, parent_index); return parent_rate / ccu_mux_get_prediv(common, cm, parent_index);
} }
EXPORT_SYMBOL_NS_GPL(ccu_mux_helper_apply_prediv, SUNXI_CCU);
static unsigned long ccu_mux_helper_unapply_prediv(struct ccu_common *common, static unsigned long ccu_mux_helper_unapply_prediv(struct ccu_common *common,
struct ccu_mux_internal *cm, struct ccu_mux_internal *cm,
@ -152,6 +153,7 @@ out:
req->rate = best_rate; req->rate = best_rate;
return 0; return 0;
} }
EXPORT_SYMBOL_NS_GPL(ccu_mux_helper_determine_rate, SUNXI_CCU);
u8 ccu_mux_helper_get_parent(struct ccu_common *common, u8 ccu_mux_helper_get_parent(struct ccu_common *common,
struct ccu_mux_internal *cm) struct ccu_mux_internal *cm)
@ -174,6 +176,7 @@ u8 ccu_mux_helper_get_parent(struct ccu_common *common,
return parent; return parent;
} }
EXPORT_SYMBOL_NS_GPL(ccu_mux_helper_get_parent, SUNXI_CCU);
int ccu_mux_helper_set_parent(struct ccu_common *common, int ccu_mux_helper_set_parent(struct ccu_common *common,
struct ccu_mux_internal *cm, struct ccu_mux_internal *cm,
@ -195,6 +198,7 @@ int ccu_mux_helper_set_parent(struct ccu_common *common,
return 0; return 0;
} }
EXPORT_SYMBOL_NS_GPL(ccu_mux_helper_set_parent, SUNXI_CCU);
static void ccu_mux_disable(struct clk_hw *hw) static void ccu_mux_disable(struct clk_hw *hw)
{ {
@ -251,6 +255,7 @@ const struct clk_ops ccu_mux_ops = {
.determine_rate = __clk_mux_determine_rate, .determine_rate = __clk_mux_determine_rate,
.recalc_rate = ccu_mux_recalc_rate, .recalc_rate = ccu_mux_recalc_rate,
}; };
EXPORT_SYMBOL_NS_GPL(ccu_mux_ops, SUNXI_CCU);
/* /*
* This clock notifier is called when the frequency of the of the parent * This clock notifier is called when the frequency of the of the parent
@ -285,3 +290,4 @@ int ccu_mux_notifier_register(struct clk *clk, struct ccu_mux_nb *mux_nb)
return clk_notifier_register(clk, &mux_nb->clk_nb); return clk_notifier_register(clk, &mux_nb->clk_nb);
} }
EXPORT_SYMBOL_NS_GPL(ccu_mux_notifier_register, SUNXI_CCU);

View File

@ -72,6 +72,39 @@ struct ccu_mux {
SUNXI_CCU_MUX_TABLE_WITH_GATE(_struct, _name, _parents, NULL, \ SUNXI_CCU_MUX_TABLE_WITH_GATE(_struct, _name, _parents, NULL, \
_reg, _shift, _width, 0, _flags) _reg, _shift, _width, 0, _flags)
#define SUNXI_CCU_MUX_DATA_WITH_GATE(_struct, _name, _parents, _reg, \
_shift, _width, _gate, _flags) \
struct ccu_mux _struct = { \
.enable = _gate, \
.mux = _SUNXI_CCU_MUX(_shift, _width), \
.common = { \
.reg = _reg, \
.hw.init = CLK_HW_INIT_PARENTS_DATA(_name, \
_parents, \
&ccu_mux_ops, \
_flags), \
} \
}
#define SUNXI_CCU_MUX_DATA(_struct, _name, _parents, _reg, \
_shift, _width, _flags) \
SUNXI_CCU_MUX_DATA_WITH_GATE(_struct, _name, _parents, _reg, \
_shift, _width, 0, _flags)
#define SUNXI_CCU_MUX_HW_WITH_GATE(_struct, _name, _parents, _reg, \
_shift, _width, _gate, _flags) \
struct ccu_mux _struct = { \
.enable = _gate, \
.mux = _SUNXI_CCU_MUX(_shift, _width), \
.common = { \
.reg = _reg, \
.hw.init = CLK_HW_INIT_PARENTS_HW(_name, \
_parents, \
&ccu_mux_ops, \
_flags), \
} \
}
static inline struct ccu_mux *hw_to_ccu_mux(struct clk_hw *hw) static inline struct ccu_mux *hw_to_ccu_mux(struct clk_hw *hw)
{ {
struct ccu_common *common = hw_to_ccu_common(hw); struct ccu_common *common = hw_to_ccu_common(hw);

View File

@ -157,3 +157,4 @@ const struct clk_ops ccu_nk_ops = {
.round_rate = ccu_nk_round_rate, .round_rate = ccu_nk_round_rate,
.set_rate = ccu_nk_set_rate, .set_rate = ccu_nk_set_rate,
}; };
EXPORT_SYMBOL_NS_GPL(ccu_nk_ops, SUNXI_CCU);

View File

@ -206,3 +206,4 @@ const struct clk_ops ccu_nkm_ops = {
.recalc_rate = ccu_nkm_recalc_rate, .recalc_rate = ccu_nkm_recalc_rate,
.set_rate = ccu_nkm_set_rate, .set_rate = ccu_nkm_set_rate,
}; };
EXPORT_SYMBOL_NS_GPL(ccu_nkm_ops, SUNXI_CCU);

View File

@ -230,3 +230,4 @@ const struct clk_ops ccu_nkmp_ops = {
.round_rate = ccu_nkmp_round_rate, .round_rate = ccu_nkmp_round_rate,
.set_rate = ccu_nkmp_set_rate, .set_rate = ccu_nkmp_set_rate,
}; };
EXPORT_SYMBOL_NS_GPL(ccu_nkmp_ops, SUNXI_CCU);

View File

@ -238,3 +238,4 @@ const struct clk_ops ccu_nm_ops = {
.round_rate = ccu_nm_round_rate, .round_rate = ccu_nm_round_rate,
.set_rate = ccu_nm_set_rate, .set_rate = ccu_nm_set_rate,
}; };
EXPORT_SYMBOL_NS_GPL(ccu_nm_ops, SUNXI_CCU);

View File

@ -121,3 +121,4 @@ const struct clk_ops ccu_phase_ops = {
.get_phase = ccu_phase_get_phase, .get_phase = ccu_phase_get_phase,
.set_phase = ccu_phase_set_phase, .set_phase = ccu_phase_set_phase,
}; };
EXPORT_SYMBOL_NS_GPL(ccu_phase_ops, SUNXI_CCU);

View File

@ -75,3 +75,4 @@ const struct reset_control_ops ccu_reset_ops = {
.reset = ccu_reset_reset, .reset = ccu_reset_reset,
.status = ccu_reset_status, .status = ccu_reset_status,
}; };
EXPORT_SYMBOL_NS_GPL(ccu_reset_ops, SUNXI_CCU);

View File

@ -20,6 +20,7 @@ bool ccu_sdm_helper_is_enabled(struct ccu_common *common,
return !!(readl(common->base + sdm->tuning_reg) & sdm->tuning_enable); return !!(readl(common->base + sdm->tuning_reg) & sdm->tuning_enable);
} }
EXPORT_SYMBOL_NS_GPL(ccu_sdm_helper_is_enabled, SUNXI_CCU);
void ccu_sdm_helper_enable(struct ccu_common *common, void ccu_sdm_helper_enable(struct ccu_common *common,
struct ccu_sdm_internal *sdm, struct ccu_sdm_internal *sdm,
@ -49,6 +50,7 @@ void ccu_sdm_helper_enable(struct ccu_common *common,
writel(reg | sdm->enable, common->base + common->reg); writel(reg | sdm->enable, common->base + common->reg);
spin_unlock_irqrestore(common->lock, flags); spin_unlock_irqrestore(common->lock, flags);
} }
EXPORT_SYMBOL_NS_GPL(ccu_sdm_helper_enable, SUNXI_CCU);
void ccu_sdm_helper_disable(struct ccu_common *common, void ccu_sdm_helper_disable(struct ccu_common *common,
struct ccu_sdm_internal *sdm) struct ccu_sdm_internal *sdm)
@ -69,6 +71,7 @@ void ccu_sdm_helper_disable(struct ccu_common *common,
writel(reg & ~sdm->tuning_enable, common->base + sdm->tuning_reg); writel(reg & ~sdm->tuning_enable, common->base + sdm->tuning_reg);
spin_unlock_irqrestore(common->lock, flags); spin_unlock_irqrestore(common->lock, flags);
} }
EXPORT_SYMBOL_NS_GPL(ccu_sdm_helper_disable, SUNXI_CCU);
/* /*
* Sigma delta modulation provides a way to do fractional-N frequency * Sigma delta modulation provides a way to do fractional-N frequency
@ -102,6 +105,7 @@ bool ccu_sdm_helper_has_rate(struct ccu_common *common,
return false; return false;
} }
EXPORT_SYMBOL_NS_GPL(ccu_sdm_helper_has_rate, SUNXI_CCU);
unsigned long ccu_sdm_helper_read_rate(struct ccu_common *common, unsigned long ccu_sdm_helper_read_rate(struct ccu_common *common,
struct ccu_sdm_internal *sdm, struct ccu_sdm_internal *sdm,
@ -132,6 +136,7 @@ unsigned long ccu_sdm_helper_read_rate(struct ccu_common *common,
/* We can't calculate the effective clock rate, so just fail. */ /* We can't calculate the effective clock rate, so just fail. */
return 0; return 0;
} }
EXPORT_SYMBOL_NS_GPL(ccu_sdm_helper_read_rate, SUNXI_CCU);
int ccu_sdm_helper_get_factors(struct ccu_common *common, int ccu_sdm_helper_get_factors(struct ccu_common *common,
struct ccu_sdm_internal *sdm, struct ccu_sdm_internal *sdm,
@ -153,3 +158,4 @@ int ccu_sdm_helper_get_factors(struct ccu_common *common,
/* nothing found */ /* nothing found */
return -EINVAL; return -EINVAL;
} }
EXPORT_SYMBOL_NS_GPL(ccu_sdm_helper_get_factors, SUNXI_CCU);

View File

@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
/* /*
* clock framework for AMD Stoney based clocks * clock framework for AMD FCH controller block
* *
* Copyright 2018 Advanced Micro Devices, Inc. * Copyright 2018 Advanced Micro Devices, Inc.
*/ */
@ -8,6 +8,7 @@
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/clkdev.h> #include <linux/clkdev.h>
#include <linux/clk-provider.h> #include <linux/clk-provider.h>
#include <linux/pci.h>
#include <linux/platform_data/clk-fch.h> #include <linux/platform_data/clk-fch.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
@ -26,22 +27,37 @@
#define ST_CLK_GATE 3 #define ST_CLK_GATE 3
#define ST_MAX_CLKS 4 #define ST_MAX_CLKS 4
#define RV_CLK_48M 0 #define CLK_48M_FIXED 0
#define RV_CLK_GATE 1 #define CLK_GATE_FIXED 1
#define RV_MAX_CLKS 2 #define CLK_MAX_FIXED 2
/* List of supported CPU ids for clk mux with 25Mhz clk support */
#define AMD_CPU_ID_ST 0x1576
static const char * const clk_oscout1_parents[] = { "clk48MHz", "clk25MHz" }; static const char * const clk_oscout1_parents[] = { "clk48MHz", "clk25MHz" };
static struct clk_hw *hws[ST_MAX_CLKS]; static struct clk_hw *hws[ST_MAX_CLKS];
static const struct pci_device_id fch_pci_ids[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, AMD_CPU_ID_ST) },
{ }
};
static int fch_clk_probe(struct platform_device *pdev) static int fch_clk_probe(struct platform_device *pdev)
{ {
struct fch_clk_data *fch_data; struct fch_clk_data *fch_data;
struct pci_dev *rdev;
fch_data = dev_get_platdata(&pdev->dev); fch_data = dev_get_platdata(&pdev->dev);
if (!fch_data || !fch_data->base) if (!fch_data || !fch_data->base)
return -EINVAL; return -EINVAL;
if (!fch_data->is_rv) { rdev = pci_get_domain_bus_and_slot(0, 0, PCI_DEVFN(0, 0));
if (!rdev) {
dev_err(&pdev->dev, "FCH device not found\n");
return -ENODEV;
}
if (pci_match_id(fch_pci_ids, rdev)) {
hws[ST_CLK_48M] = clk_hw_register_fixed_rate(NULL, "clk48MHz", hws[ST_CLK_48M] = clk_hw_register_fixed_rate(NULL, "clk48MHz",
NULL, 0, 48000000); NULL, 0, 48000000);
hws[ST_CLK_25M] = clk_hw_register_fixed_rate(NULL, "clk25MHz", hws[ST_CLK_25M] = clk_hw_register_fixed_rate(NULL, "clk25MHz",
@ -59,34 +75,38 @@ static int fch_clk_probe(struct platform_device *pdev)
OSCCLKENB, CLK_GATE_SET_TO_DISABLE, NULL); OSCCLKENB, CLK_GATE_SET_TO_DISABLE, NULL);
devm_clk_hw_register_clkdev(&pdev->dev, hws[ST_CLK_GATE], devm_clk_hw_register_clkdev(&pdev->dev, hws[ST_CLK_GATE],
"oscout1", NULL); fch_data->name, NULL);
} else { } else {
hws[RV_CLK_48M] = clk_hw_register_fixed_rate(NULL, "clk48MHz", hws[CLK_48M_FIXED] = clk_hw_register_fixed_rate(NULL, "clk48MHz",
NULL, 0, 48000000); NULL, 0, 48000000);
hws[RV_CLK_GATE] = clk_hw_register_gate(NULL, "oscout1", hws[CLK_GATE_FIXED] = clk_hw_register_gate(NULL, "oscout1",
"clk48MHz", 0, fch_data->base + MISCCLKCNTL1, "clk48MHz", 0, fch_data->base + MISCCLKCNTL1,
OSCCLKENB, CLK_GATE_SET_TO_DISABLE, NULL); OSCCLKENB, 0, NULL);
devm_clk_hw_register_clkdev(&pdev->dev, hws[RV_CLK_GATE], devm_clk_hw_register_clkdev(&pdev->dev, hws[CLK_GATE_FIXED],
"oscout1", NULL); fch_data->name, NULL);
} }
pci_dev_put(rdev);
return 0; return 0;
} }
static int fch_clk_remove(struct platform_device *pdev) static int fch_clk_remove(struct platform_device *pdev)
{ {
int i, clks; int i, clks;
struct fch_clk_data *fch_data; struct pci_dev *rdev;
fch_data = dev_get_platdata(&pdev->dev); rdev = pci_get_domain_bus_and_slot(0, 0, PCI_DEVFN(0, 0));
if (!rdev)
return -ENODEV;
clks = fch_data->is_rv ? RV_MAX_CLKS : ST_MAX_CLKS; clks = pci_match_id(fch_pci_ids, rdev) ? CLK_MAX_FIXED : ST_MAX_CLKS;
for (i = 0; i < clks; i++) for (i = 0; i < clks; i++)
clk_hw_unregister(hws[i]); clk_hw_unregister(hws[i]);
pci_dev_put(rdev);
return 0; return 0;
} }

View File

@ -144,9 +144,12 @@ static int i2c_acpi_do_lookup(struct acpi_device *adev,
struct list_head resource_list; struct list_head resource_list;
int ret; int ret;
if (acpi_bus_get_status(adev) || !adev->status.present) if (acpi_bus_get_status(adev))
return -EINVAL; return -EINVAL;
if (!acpi_dev_ready_for_enumeration(adev))
return -ENODEV;
if (acpi_match_device_ids(adev, i2c_acpi_ignored_device_ids) == 0) if (acpi_match_device_ids(adev, i2c_acpi_ignored_device_ids) == 0)
return -ENODEV; return -ENODEV;
@ -473,8 +476,8 @@ struct notifier_block i2c_acpi_notifier = {
}; };
/** /**
* i2c_acpi_new_device - Create i2c-client for the Nth I2cSerialBus resource * i2c_acpi_new_device_by_fwnode - Create i2c-client for the Nth I2cSerialBus resource
* @dev: Device owning the ACPI resources to get the client from * @fwnode: fwnode with the ACPI resources to get the client from
* @index: Index of ACPI resource to get * @index: Index of ACPI resource to get
* @info: describes the I2C device; note this is modified (addr gets set) * @info: describes the I2C device; note this is modified (addr gets set)
* Context: can sleep * Context: can sleep
@ -490,15 +493,20 @@ struct notifier_block i2c_acpi_notifier = {
* Returns a pointer to the new i2c-client, or error pointer in case of failure. * Returns a pointer to the new i2c-client, or error pointer in case of failure.
* Specifically, -EPROBE_DEFER is returned if the adapter is not found. * Specifically, -EPROBE_DEFER is returned if the adapter is not found.
*/ */
struct i2c_client *i2c_acpi_new_device(struct device *dev, int index, struct i2c_client *i2c_acpi_new_device_by_fwnode(struct fwnode_handle *fwnode,
struct i2c_board_info *info) int index,
struct i2c_board_info *info)
{ {
struct acpi_device *adev = ACPI_COMPANION(dev);
struct i2c_acpi_lookup lookup; struct i2c_acpi_lookup lookup;
struct i2c_adapter *adapter; struct i2c_adapter *adapter;
struct acpi_device *adev;
LIST_HEAD(resource_list); LIST_HEAD(resource_list);
int ret; int ret;
adev = to_acpi_device_node(fwnode);
if (!adev)
return ERR_PTR(-ENODEV);
memset(&lookup, 0, sizeof(lookup)); memset(&lookup, 0, sizeof(lookup));
lookup.info = info; lookup.info = info;
lookup.device_handle = acpi_device_handle(adev); lookup.device_handle = acpi_device_handle(adev);
@ -520,7 +528,7 @@ struct i2c_client *i2c_acpi_new_device(struct device *dev, int index,
return i2c_new_client_device(adapter, info); return i2c_new_client_device(adapter, info);
} }
EXPORT_SYMBOL_GPL(i2c_acpi_new_device); EXPORT_SYMBOL_GPL(i2c_acpi_new_device_by_fwnode);
bool i2c_acpi_waive_d0_probe(struct device *dev) bool i2c_acpi_waive_d0_probe(struct device *dev)
{ {

View File

@ -966,6 +966,7 @@ config MMC_REALTEK_USB
config MMC_SUNXI config MMC_SUNXI
tristate "Allwinner sunxi SD/MMC Host Controller support" tristate "Allwinner sunxi SD/MMC Host Controller support"
depends on ARCH_SUNXI || COMPILE_TEST depends on ARCH_SUNXI || COMPILE_TEST
depends on SUNXI_CCU
help help
This selects support for the SD/MMC Host Controller on This selects support for the SD/MMC Host Controller on
Allwinner sunxi SoCs. Allwinner sunxi SoCs.

View File

@ -1,5 +1,4 @@
obj-$(CONFIG_INTEL_SKL_INT3472) += intel_skl_int3472.o obj-$(CONFIG_INTEL_SKL_INT3472) += intel_skl_int3472_discrete.o \
intel_skl_int3472-y := intel_skl_int3472_common.o \ intel_skl_int3472_tps68470.o
intel_skl_int3472_discrete.o \ intel_skl_int3472_discrete-y := discrete.o clk_and_regulator.o common.o
intel_skl_int3472_tps68470.o \ intel_skl_int3472_tps68470-y := tps68470.o tps68470_board_data.o common.o
intel_skl_int3472_clk_and_regulator.o

View File

@ -9,7 +9,7 @@
#include <linux/regulator/driver.h> #include <linux/regulator/driver.h>
#include <linux/slab.h> #include <linux/slab.h>
#include "intel_skl_int3472_common.h" #include "common.h"
/* /*
* The regulators have to have .ops to be valid, but the only ops we actually * The regulators have to have .ops to be valid, but the only ops we actually

View File

@ -0,0 +1,82 @@
// SPDX-License-Identifier: GPL-2.0
/* Author: Dan Scally <djrscally@gmail.com> */
#include <linux/acpi.h>
#include <linux/slab.h>
#include "common.h"
union acpi_object *skl_int3472_get_acpi_buffer(struct acpi_device *adev, char *id)
{
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
acpi_handle handle = adev->handle;
union acpi_object *obj;
acpi_status status;
status = acpi_evaluate_object(handle, id, NULL, &buffer);
if (ACPI_FAILURE(status))
return ERR_PTR(-ENODEV);
obj = buffer.pointer;
if (!obj)
return ERR_PTR(-ENODEV);
if (obj->type != ACPI_TYPE_BUFFER) {
acpi_handle_err(handle, "%s object is not an ACPI buffer\n", id);
kfree(obj);
return ERR_PTR(-EINVAL);
}
return obj;
}
int skl_int3472_fill_cldb(struct acpi_device *adev, struct int3472_cldb *cldb)
{
union acpi_object *obj;
int ret;
obj = skl_int3472_get_acpi_buffer(adev, "CLDB");
if (IS_ERR(obj))
return PTR_ERR(obj);
if (obj->buffer.length > sizeof(*cldb)) {
acpi_handle_err(adev->handle, "The CLDB buffer is too large\n");
ret = -EINVAL;
goto out_free_obj;
}
memcpy(cldb, obj->buffer.pointer, obj->buffer.length);
ret = 0;
out_free_obj:
kfree(obj);
return ret;
}
/* sensor_adev_ret may be NULL, name_ret must not be NULL */
int skl_int3472_get_sensor_adev_and_name(struct device *dev,
struct acpi_device **sensor_adev_ret,
const char **name_ret)
{
struct acpi_device *adev = ACPI_COMPANION(dev);
struct acpi_device *sensor;
int ret = 0;
sensor = acpi_dev_get_first_consumer_dev(adev);
if (!sensor) {
dev_err(dev, "INT3472 seems to have no dependents.\n");
return -ENODEV;
}
*name_ret = devm_kasprintf(dev, GFP_KERNEL, I2C_DEV_NAME_FORMAT,
acpi_dev_name(sensor));
if (!*name_ret)
ret = -ENOMEM;
if (ret == 0 && sensor_adev_ret)
*sensor_adev_ret = sensor;
else
acpi_dev_put(sensor);
return ret;
}

View File

@ -105,12 +105,12 @@ struct int3472_discrete_device {
struct gpiod_lookup_table gpios; struct gpiod_lookup_table gpios;
}; };
int skl_int3472_discrete_probe(struct platform_device *pdev);
int skl_int3472_discrete_remove(struct platform_device *pdev);
int skl_int3472_tps68470_probe(struct i2c_client *client);
union acpi_object *skl_int3472_get_acpi_buffer(struct acpi_device *adev, union acpi_object *skl_int3472_get_acpi_buffer(struct acpi_device *adev,
char *id); char *id);
int skl_int3472_fill_cldb(struct acpi_device *adev, struct int3472_cldb *cldb); int skl_int3472_fill_cldb(struct acpi_device *adev, struct int3472_cldb *cldb);
int skl_int3472_get_sensor_adev_and_name(struct device *dev,
struct acpi_device **sensor_adev_ret,
const char **name_ret);
int skl_int3472_register_clock(struct int3472_discrete_device *int3472); int skl_int3472_register_clock(struct int3472_discrete_device *int3472);
void skl_int3472_unregister_clock(struct int3472_discrete_device *int3472); void skl_int3472_unregister_clock(struct int3472_discrete_device *int3472);

View File

@ -14,7 +14,7 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/uuid.h> #include <linux/uuid.h>
#include "intel_skl_int3472_common.h" #include "common.h"
/* /*
* 79234640-9e10-4fea-a5c1-b5aa8b19756f * 79234640-9e10-4fea-a5c1-b5aa8b19756f
@ -332,7 +332,9 @@ static int skl_int3472_parse_crs(struct int3472_discrete_device *int3472)
return 0; return 0;
} }
int skl_int3472_discrete_probe(struct platform_device *pdev) static int skl_int3472_discrete_remove(struct platform_device *pdev);
static int skl_int3472_discrete_probe(struct platform_device *pdev)
{ {
struct acpi_device *adev = ACPI_COMPANION(&pdev->dev); struct acpi_device *adev = ACPI_COMPANION(&pdev->dev);
struct int3472_discrete_device *int3472; struct int3472_discrete_device *int3472;
@ -361,19 +363,10 @@ int skl_int3472_discrete_probe(struct platform_device *pdev)
int3472->dev = &pdev->dev; int3472->dev = &pdev->dev;
platform_set_drvdata(pdev, int3472); platform_set_drvdata(pdev, int3472);
int3472->sensor = acpi_dev_get_first_consumer_dev(adev); ret = skl_int3472_get_sensor_adev_and_name(&pdev->dev, &int3472->sensor,
if (!int3472->sensor) { &int3472->sensor_name);
dev_err(&pdev->dev, "INT3472 seems to have no dependents.\n"); if (ret)
return -ENODEV; return ret;
}
int3472->sensor_name = devm_kasprintf(int3472->dev, GFP_KERNEL,
I2C_DEV_NAME_FORMAT,
acpi_dev_name(int3472->sensor));
if (!int3472->sensor_name) {
ret = -ENOMEM;
goto err_put_sensor;
}
/* /*
* Initialising this list means we can call gpiod_remove_lookup_table() * Initialising this list means we can call gpiod_remove_lookup_table()
@ -387,15 +380,11 @@ int skl_int3472_discrete_probe(struct platform_device *pdev)
return ret; return ret;
} }
acpi_dev_clear_dependencies(adev);
return 0; return 0;
err_put_sensor:
acpi_dev_put(int3472->sensor);
return ret;
} }
int skl_int3472_discrete_remove(struct platform_device *pdev) static int skl_int3472_discrete_remove(struct platform_device *pdev)
{ {
struct int3472_discrete_device *int3472 = platform_get_drvdata(pdev); struct int3472_discrete_device *int3472 = platform_get_drvdata(pdev);
@ -411,3 +400,23 @@ int skl_int3472_discrete_remove(struct platform_device *pdev)
return 0; return 0;
} }
static const struct acpi_device_id int3472_device_id[] = {
{ "INT3472", 0 },
{ }
};
MODULE_DEVICE_TABLE(acpi, int3472_device_id);
static struct platform_driver int3472_discrete = {
.driver = {
.name = "int3472-discrete",
.acpi_match_table = int3472_device_id,
},
.probe = skl_int3472_discrete_probe,
.remove = skl_int3472_discrete_remove,
};
module_platform_driver(int3472_discrete);
MODULE_DESCRIPTION("Intel SkyLake INT3472 ACPI Discrete Device Driver");
MODULE_AUTHOR("Daniel Scally <djrscally@gmail.com>");
MODULE_LICENSE("GPL v2");

View File

@ -1,106 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
/* Author: Dan Scally <djrscally@gmail.com> */
#include <linux/acpi.h>
#include <linux/i2c.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include "intel_skl_int3472_common.h"
union acpi_object *skl_int3472_get_acpi_buffer(struct acpi_device *adev, char *id)
{
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
acpi_handle handle = adev->handle;
union acpi_object *obj;
acpi_status status;
status = acpi_evaluate_object(handle, id, NULL, &buffer);
if (ACPI_FAILURE(status))
return ERR_PTR(-ENODEV);
obj = buffer.pointer;
if (!obj)
return ERR_PTR(-ENODEV);
if (obj->type != ACPI_TYPE_BUFFER) {
acpi_handle_err(handle, "%s object is not an ACPI buffer\n", id);
kfree(obj);
return ERR_PTR(-EINVAL);
}
return obj;
}
int skl_int3472_fill_cldb(struct acpi_device *adev, struct int3472_cldb *cldb)
{
union acpi_object *obj;
int ret;
obj = skl_int3472_get_acpi_buffer(adev, "CLDB");
if (IS_ERR(obj))
return PTR_ERR(obj);
if (obj->buffer.length > sizeof(*cldb)) {
acpi_handle_err(adev->handle, "The CLDB buffer is too large\n");
ret = -EINVAL;
goto out_free_obj;
}
memcpy(cldb, obj->buffer.pointer, obj->buffer.length);
ret = 0;
out_free_obj:
kfree(obj);
return ret;
}
static const struct acpi_device_id int3472_device_id[] = {
{ "INT3472", 0 },
{ }
};
MODULE_DEVICE_TABLE(acpi, int3472_device_id);
static struct platform_driver int3472_discrete = {
.driver = {
.name = "int3472-discrete",
.acpi_match_table = int3472_device_id,
},
.probe = skl_int3472_discrete_probe,
.remove = skl_int3472_discrete_remove,
};
static struct i2c_driver int3472_tps68470 = {
.driver = {
.name = "int3472-tps68470",
.acpi_match_table = int3472_device_id,
},
.probe_new = skl_int3472_tps68470_probe,
};
static int skl_int3472_init(void)
{
int ret;
ret = platform_driver_register(&int3472_discrete);
if (ret)
return ret;
ret = i2c_register_driver(THIS_MODULE, &int3472_tps68470);
if (ret)
platform_driver_unregister(&int3472_discrete);
return ret;
}
module_init(skl_int3472_init);
static void skl_int3472_exit(void)
{
platform_driver_unregister(&int3472_discrete);
i2c_del_driver(&int3472_tps68470);
}
module_exit(skl_int3472_exit);
MODULE_DESCRIPTION("Intel SkyLake INT3472 ACPI Device Driver");
MODULE_AUTHOR("Daniel Scally <djrscally@gmail.com>");
MODULE_LICENSE("GPL v2");

View File

@ -2,27 +2,27 @@
/* Author: Dan Scally <djrscally@gmail.com> */ /* Author: Dan Scally <djrscally@gmail.com> */
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/kernel.h>
#include <linux/mfd/core.h> #include <linux/mfd/core.h>
#include <linux/mfd/tps68470.h> #include <linux/mfd/tps68470.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/platform_data/tps68470.h>
#include <linux/regmap.h> #include <linux/regmap.h>
#include <linux/string.h>
#include "intel_skl_int3472_common.h" #include "common.h"
#include "tps68470.h"
#define DESIGNED_FOR_CHROMEOS 1 #define DESIGNED_FOR_CHROMEOS 1
#define DESIGNED_FOR_WINDOWS 2 #define DESIGNED_FOR_WINDOWS 2
#define TPS68470_WIN_MFD_CELL_COUNT 3
static const struct mfd_cell tps68470_cros[] = { static const struct mfd_cell tps68470_cros[] = {
{ .name = "tps68470-gpio" }, { .name = "tps68470-gpio" },
{ .name = "tps68470_pmic_opregion" }, { .name = "tps68470_pmic_opregion" },
}; };
static const struct mfd_cell tps68470_win[] = {
{ .name = "tps68470-gpio" },
{ .name = "tps68470-clk" },
{ .name = "tps68470-regulator" },
};
static const struct regmap_config tps68470_regmap_config = { static const struct regmap_config tps68470_regmap_config = {
.reg_bits = 8, .reg_bits = 8,
.val_bits = 8, .val_bits = 8,
@ -95,13 +95,21 @@ static int skl_int3472_tps68470_calc_type(struct acpi_device *adev)
return DESIGNED_FOR_WINDOWS; return DESIGNED_FOR_WINDOWS;
} }
int skl_int3472_tps68470_probe(struct i2c_client *client) static int skl_int3472_tps68470_probe(struct i2c_client *client)
{ {
struct acpi_device *adev = ACPI_COMPANION(&client->dev); struct acpi_device *adev = ACPI_COMPANION(&client->dev);
const struct int3472_tps68470_board_data *board_data;
struct tps68470_clk_platform_data clk_pdata = {};
struct mfd_cell *cells;
struct regmap *regmap; struct regmap *regmap;
int device_type; int device_type;
int ret; int ret;
ret = skl_int3472_get_sensor_adev_and_name(&client->dev, NULL,
&clk_pdata.consumer_dev_name);
if (ret)
return ret;
regmap = devm_regmap_init_i2c(client, &tps68470_regmap_config); regmap = devm_regmap_init_i2c(client, &tps68470_regmap_config);
if (IS_ERR(regmap)) { if (IS_ERR(regmap)) {
dev_err(&client->dev, "Failed to create regmap: %ld\n", PTR_ERR(regmap)); dev_err(&client->dev, "Failed to create regmap: %ld\n", PTR_ERR(regmap));
@ -119,9 +127,38 @@ int skl_int3472_tps68470_probe(struct i2c_client *client)
device_type = skl_int3472_tps68470_calc_type(adev); device_type = skl_int3472_tps68470_calc_type(adev);
switch (device_type) { switch (device_type) {
case DESIGNED_FOR_WINDOWS: case DESIGNED_FOR_WINDOWS:
board_data = int3472_tps68470_get_board_data(dev_name(&client->dev));
if (!board_data)
return dev_err_probe(&client->dev, -ENODEV, "No board-data found for this model\n");
cells = kcalloc(TPS68470_WIN_MFD_CELL_COUNT, sizeof(*cells), GFP_KERNEL);
if (!cells)
return -ENOMEM;
/*
* The order of the cells matters here! The clk must be first
* because the regulator depends on it. The gpios must be last,
* acpi_gpiochip_add() calls acpi_dev_clear_dependencies() and
* the clk + regulators must be ready when this happens.
*/
cells[0].name = "tps68470-clk";
cells[0].platform_data = &clk_pdata;
cells[0].pdata_size = sizeof(clk_pdata);
cells[1].name = "tps68470-regulator";
cells[1].platform_data = (void *)board_data->tps68470_regulator_pdata;
cells[1].pdata_size = sizeof(struct tps68470_regulator_platform_data);
cells[2].name = "tps68470-gpio";
gpiod_add_lookup_table(board_data->tps68470_gpio_lookup_table);
ret = devm_mfd_add_devices(&client->dev, PLATFORM_DEVID_NONE, ret = devm_mfd_add_devices(&client->dev, PLATFORM_DEVID_NONE,
tps68470_win, ARRAY_SIZE(tps68470_win), cells, TPS68470_WIN_MFD_CELL_COUNT,
NULL, 0, NULL); NULL, 0, NULL);
kfree(cells);
if (ret)
gpiod_remove_lookup_table(board_data->tps68470_gpio_lookup_table);
break; break;
case DESIGNED_FOR_CHROMEOS: case DESIGNED_FOR_CHROMEOS:
ret = devm_mfd_add_devices(&client->dev, PLATFORM_DEVID_NONE, ret = devm_mfd_add_devices(&client->dev, PLATFORM_DEVID_NONE,
@ -133,5 +170,42 @@ int skl_int3472_tps68470_probe(struct i2c_client *client)
return device_type; return device_type;
} }
/*
* No acpi_dev_clear_dependencies() here, since the acpi_gpiochip_add()
* for the GPIO cell already does this.
*/
return ret; return ret;
} }
static int skl_int3472_tps68470_remove(struct i2c_client *client)
{
const struct int3472_tps68470_board_data *board_data;
board_data = int3472_tps68470_get_board_data(dev_name(&client->dev));
if (board_data)
gpiod_remove_lookup_table(board_data->tps68470_gpio_lookup_table);
return 0;
}
static const struct acpi_device_id int3472_device_id[] = {
{ "INT3472", 0 },
{ }
};
MODULE_DEVICE_TABLE(acpi, int3472_device_id);
static struct i2c_driver int3472_tps68470 = {
.driver = {
.name = "int3472-tps68470",
.acpi_match_table = int3472_device_id,
},
.probe_new = skl_int3472_tps68470_probe,
.remove = skl_int3472_tps68470_remove,
};
module_i2c_driver(int3472_tps68470);
MODULE_DESCRIPTION("Intel SkyLake INT3472 ACPI TPS68470 Device Driver");
MODULE_AUTHOR("Daniel Scally <djrscally@gmail.com>");
MODULE_LICENSE("GPL v2");
MODULE_SOFTDEP("pre: clk-tps68470 tps68470-regulator");

View File

@ -0,0 +1,25 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* TI TPS68470 PMIC platform data definition.
*
* Copyright (c) 2021 Red Hat Inc.
*
* Red Hat authors:
* Hans de Goede <hdegoede@redhat.com>
*/
#ifndef _INTEL_SKL_INT3472_TPS68470_H
#define _INTEL_SKL_INT3472_TPS68470_H
struct gpiod_lookup_table;
struct tps68470_regulator_platform_data;
struct int3472_tps68470_board_data {
const char *dev_name;
struct gpiod_lookup_table *tps68470_gpio_lookup_table;
const struct tps68470_regulator_platform_data *tps68470_regulator_pdata;
};
const struct int3472_tps68470_board_data *int3472_tps68470_get_board_data(const char *dev_name);
#endif

View File

@ -0,0 +1,145 @@
// SPDX-License-Identifier: GPL-2.0
/*
* TI TPS68470 PMIC platform data definition.
*
* Copyright (c) 2021 Dan Scally <djrscally@gmail.com>
* Copyright (c) 2021 Red Hat Inc.
*
* Red Hat authors:
* Hans de Goede <hdegoede@redhat.com>
*/
#include <linux/dmi.h>
#include <linux/gpio/machine.h>
#include <linux/platform_data/tps68470.h>
#include <linux/regulator/machine.h>
#include "tps68470.h"
static struct regulator_consumer_supply int347a_core_consumer_supplies[] = {
REGULATOR_SUPPLY("dvdd", "i2c-INT347A:00"),
};
static struct regulator_consumer_supply int347a_ana_consumer_supplies[] = {
REGULATOR_SUPPLY("avdd", "i2c-INT347A:00"),
};
static struct regulator_consumer_supply int347a_vcm_consumer_supplies[] = {
REGULATOR_SUPPLY("vdd", "i2c-INT347A:00-VCM"),
};
static struct regulator_consumer_supply int347a_vsio_consumer_supplies[] = {
REGULATOR_SUPPLY("dovdd", "i2c-INT347A:00"),
REGULATOR_SUPPLY("vsio", "i2c-INT347A:00-VCM"),
};
static const struct regulator_init_data surface_go_tps68470_core_reg_init_data = {
.constraints = {
.min_uV = 1200000,
.max_uV = 1200000,
.apply_uV = true,
.valid_ops_mask = REGULATOR_CHANGE_STATUS,
},
.num_consumer_supplies = ARRAY_SIZE(int347a_core_consumer_supplies),
.consumer_supplies = int347a_core_consumer_supplies,
};
static const struct regulator_init_data surface_go_tps68470_ana_reg_init_data = {
.constraints = {
.min_uV = 2815200,
.max_uV = 2815200,
.apply_uV = true,
.valid_ops_mask = REGULATOR_CHANGE_STATUS,
},
.num_consumer_supplies = ARRAY_SIZE(int347a_ana_consumer_supplies),
.consumer_supplies = int347a_ana_consumer_supplies,
};
static const struct regulator_init_data surface_go_tps68470_vcm_reg_init_data = {
.constraints = {
.min_uV = 2815200,
.max_uV = 2815200,
.apply_uV = true,
.valid_ops_mask = REGULATOR_CHANGE_STATUS,
},
.num_consumer_supplies = ARRAY_SIZE(int347a_vcm_consumer_supplies),
.consumer_supplies = int347a_vcm_consumer_supplies,
};
/* Ensure the always-on VIO regulator has the same voltage as VSIO */
static const struct regulator_init_data surface_go_tps68470_vio_reg_init_data = {
.constraints = {
.min_uV = 1800600,
.max_uV = 1800600,
.apply_uV = true,
.always_on = true,
},
};
static const struct regulator_init_data surface_go_tps68470_vsio_reg_init_data = {
.constraints = {
.min_uV = 1800600,
.max_uV = 1800600,
.apply_uV = true,
.valid_ops_mask = REGULATOR_CHANGE_STATUS,
},
.num_consumer_supplies = ARRAY_SIZE(int347a_vsio_consumer_supplies),
.consumer_supplies = int347a_vsio_consumer_supplies,
};
static const struct tps68470_regulator_platform_data surface_go_tps68470_pdata = {
.reg_init_data = {
[TPS68470_CORE] = &surface_go_tps68470_core_reg_init_data,
[TPS68470_ANA] = &surface_go_tps68470_ana_reg_init_data,
[TPS68470_VCM] = &surface_go_tps68470_vcm_reg_init_data,
[TPS68470_VIO] = &surface_go_tps68470_vio_reg_init_data,
[TPS68470_VSIO] = &surface_go_tps68470_vsio_reg_init_data,
},
};
static struct gpiod_lookup_table surface_go_tps68470_gpios = {
.dev_id = "i2c-INT347A:00",
.table = {
GPIO_LOOKUP("tps68470-gpio", 9, "reset", GPIO_ACTIVE_LOW),
GPIO_LOOKUP("tps68470-gpio", 7, "powerdown", GPIO_ACTIVE_LOW)
}
};
static const struct int3472_tps68470_board_data surface_go_tps68470_board_data = {
.dev_name = "i2c-INT3472:05",
.tps68470_gpio_lookup_table = &surface_go_tps68470_gpios,
.tps68470_regulator_pdata = &surface_go_tps68470_pdata,
};
static const struct dmi_system_id int3472_tps68470_board_data_table[] = {
{
.matches = {
DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Surface Go"),
},
.driver_data = (void *)&surface_go_tps68470_board_data,
},
{
.matches = {
DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Surface Go 2"),
},
.driver_data = (void *)&surface_go_tps68470_board_data,
},
{ }
};
const struct int3472_tps68470_board_data *int3472_tps68470_get_board_data(const char *dev_name)
{
const struct int3472_tps68470_board_data *board_data;
const struct dmi_system_id *match;
for (match = dmi_first_match(int3472_tps68470_board_data_table);
match;
match = dmi_first_match(match + 1)) {
board_data = match->driver_data;
if (strcmp(board_data->dev_name, dev_name) == 0)
return board_data;
}
return NULL;
}

View File

@ -202,7 +202,8 @@ struct acpi_device_flags {
u32 coherent_dma:1; u32 coherent_dma:1;
u32 cca_seen:1; u32 cca_seen:1;
u32 enumeration_by_parent:1; u32 enumeration_by_parent:1;
u32 reserved:19; u32 honor_deps:1;
u32 reserved:18;
}; };
/* File System */ /* File System */
@ -285,6 +286,7 @@ struct acpi_dep_data {
struct list_head node; struct list_head node;
acpi_handle supplier; acpi_handle supplier;
acpi_handle consumer; acpi_handle consumer;
bool honor_dep;
}; };
/* Performance Management */ /* Performance Management */
@ -693,6 +695,7 @@ static inline bool acpi_device_can_poweroff(struct acpi_device *adev)
bool acpi_dev_hid_uid_match(struct acpi_device *adev, const char *hid2, const char *uid2); bool acpi_dev_hid_uid_match(struct acpi_device *adev, const char *hid2, const char *uid2);
void acpi_dev_clear_dependencies(struct acpi_device *supplier); void acpi_dev_clear_dependencies(struct acpi_device *supplier);
bool acpi_dev_ready_for_enumeration(const struct acpi_device *device);
struct acpi_device *acpi_dev_get_first_consumer_dev(struct acpi_device *supplier); struct acpi_device *acpi_dev_get_first_consumer_dev(struct acpi_device *supplier);
struct acpi_device * struct acpi_device *
acpi_dev_get_next_match_dev(struct acpi_device *adev, const char *hid, const char *uid, s64 hrv); acpi_dev_get_next_match_dev(struct acpi_device *adev, const char *hid, const char *uid, s64 hrv);

View File

@ -0,0 +1,156 @@
/* SPDX-License-Identifier: (GPL-2.0+ or MIT) */
/*
* Copyright (C) 2020 huangzhenwei@allwinnertech.com
* Copyright (C) 2021 Samuel Holland <samuel@sholland.org>
*/
#ifndef _DT_BINDINGS_CLK_SUN20I_D1_CCU_H_
#define _DT_BINDINGS_CLK_SUN20I_D1_CCU_H_
#define CLK_PLL_CPUX 0
#define CLK_PLL_DDR0 1
#define CLK_PLL_PERIPH0_4X 2
#define CLK_PLL_PERIPH0_2X 3
#define CLK_PLL_PERIPH0_800M 4
#define CLK_PLL_PERIPH0 5
#define CLK_PLL_PERIPH0_DIV3 6
#define CLK_PLL_VIDEO0_4X 7
#define CLK_PLL_VIDEO0_2X 8
#define CLK_PLL_VIDEO0 9
#define CLK_PLL_VIDEO1_4X 10
#define CLK_PLL_VIDEO1_2X 11
#define CLK_PLL_VIDEO1 12
#define CLK_PLL_VE 13
#define CLK_PLL_AUDIO0_4X 14
#define CLK_PLL_AUDIO0_2X 15
#define CLK_PLL_AUDIO0 16
#define CLK_PLL_AUDIO1 17
#define CLK_PLL_AUDIO1_DIV2 18
#define CLK_PLL_AUDIO1_DIV5 19
#define CLK_CPUX 20
#define CLK_CPUX_AXI 21
#define CLK_CPUX_APB 22
#define CLK_PSI_AHB 23
#define CLK_APB0 24
#define CLK_APB1 25
#define CLK_MBUS 26
#define CLK_DE 27
#define CLK_BUS_DE 28
#define CLK_DI 29
#define CLK_BUS_DI 30
#define CLK_G2D 31
#define CLK_BUS_G2D 32
#define CLK_CE 33
#define CLK_BUS_CE 34
#define CLK_VE 35
#define CLK_BUS_VE 36
#define CLK_BUS_DMA 37
#define CLK_BUS_MSGBOX0 38
#define CLK_BUS_MSGBOX1 39
#define CLK_BUS_MSGBOX2 40
#define CLK_BUS_SPINLOCK 41
#define CLK_BUS_HSTIMER 42
#define CLK_AVS 43
#define CLK_BUS_DBG 44
#define CLK_BUS_PWM 45
#define CLK_BUS_IOMMU 46
#define CLK_DRAM 47
#define CLK_MBUS_DMA 48
#define CLK_MBUS_VE 49
#define CLK_MBUS_CE 50
#define CLK_MBUS_TVIN 51
#define CLK_MBUS_CSI 52
#define CLK_MBUS_G2D 53
#define CLK_MBUS_RISCV 54
#define CLK_BUS_DRAM 55
#define CLK_MMC0 56
#define CLK_MMC1 57
#define CLK_MMC2 58
#define CLK_BUS_MMC0 59
#define CLK_BUS_MMC1 60
#define CLK_BUS_MMC2 61
#define CLK_BUS_UART0 62
#define CLK_BUS_UART1 63
#define CLK_BUS_UART2 64
#define CLK_BUS_UART3 65
#define CLK_BUS_UART4 66
#define CLK_BUS_UART5 67
#define CLK_BUS_I2C0 68
#define CLK_BUS_I2C1 69
#define CLK_BUS_I2C2 70
#define CLK_BUS_I2C3 71
#define CLK_SPI0 72
#define CLK_SPI1 73
#define CLK_BUS_SPI0 74
#define CLK_BUS_SPI1 75
#define CLK_EMAC_25M 76
#define CLK_BUS_EMAC 77
#define CLK_IR_TX 78
#define CLK_BUS_IR_TX 79
#define CLK_BUS_GPADC 80
#define CLK_BUS_THS 81
#define CLK_I2S0 82
#define CLK_I2S1 83
#define CLK_I2S2 84
#define CLK_I2S2_ASRC 85
#define CLK_BUS_I2S0 86
#define CLK_BUS_I2S1 87
#define CLK_BUS_I2S2 88
#define CLK_SPDIF_TX 89
#define CLK_SPDIF_RX 90
#define CLK_BUS_SPDIF 91
#define CLK_DMIC 92
#define CLK_BUS_DMIC 93
#define CLK_AUDIO_DAC 94
#define CLK_AUDIO_ADC 95
#define CLK_BUS_AUDIO 96
#define CLK_USB_OHCI0 97
#define CLK_USB_OHCI1 98
#define CLK_BUS_OHCI0 99
#define CLK_BUS_OHCI1 100
#define CLK_BUS_EHCI0 101
#define CLK_BUS_EHCI1 102
#define CLK_BUS_OTG 103
#define CLK_BUS_LRADC 104
#define CLK_BUS_DPSS_TOP 105
#define CLK_HDMI_24M 106
#define CLK_HDMI_CEC_32K 107
#define CLK_HDMI_CEC 108
#define CLK_BUS_HDMI 109
#define CLK_MIPI_DSI 110
#define CLK_BUS_MIPI_DSI 111
#define CLK_TCON_LCD0 112
#define CLK_BUS_TCON_LCD0 113
#define CLK_TCON_TV 114
#define CLK_BUS_TCON_TV 115
#define CLK_TVE 116
#define CLK_BUS_TVE_TOP 117
#define CLK_BUS_TVE 118
#define CLK_TVD 119
#define CLK_BUS_TVD_TOP 120
#define CLK_BUS_TVD 121
#define CLK_LEDC 122
#define CLK_BUS_LEDC 123
#define CLK_CSI_TOP 124
#define CLK_CSI_MCLK 125
#define CLK_BUS_CSI 126
#define CLK_TPADC 127
#define CLK_BUS_TPADC 128
#define CLK_BUS_TZMA 129
#define CLK_DSP 130
#define CLK_BUS_DSP_CFG 131
#define CLK_RISCV 132
#define CLK_RISCV_AXI 133
#define CLK_BUS_RISCV_CFG 134
#define CLK_FANOUT_24M 135
#define CLK_FANOUT_12M 136
#define CLK_FANOUT_16M 137
#define CLK_FANOUT_25M 138
#define CLK_FANOUT_32K 139
#define CLK_FANOUT_27M 140
#define CLK_FANOUT_PCLK 141
#define CLK_FANOUT0 142
#define CLK_FANOUT1 143
#define CLK_FANOUT2 144
#endif /* _DT_BINDINGS_CLK_SUN20I_D1_CCU_H_ */

View File

@ -0,0 +1,19 @@
/* SPDX-License-Identifier: (GPL-2.0+ or MIT) */
/*
* Copyright (C) 2021 Samuel Holland <samuel@sholland.org>
*/
#ifndef _DT_BINDINGS_CLK_SUN20I_D1_R_CCU_H_
#define _DT_BINDINGS_CLK_SUN20I_D1_R_CCU_H_
#define CLK_R_AHB 0
#define CLK_BUS_R_TIMER 2
#define CLK_BUS_R_TWD 3
#define CLK_BUS_R_PPU 4
#define CLK_R_IR_RX 5
#define CLK_BUS_R_IR_RX 6
#define CLK_BUS_R_RTC 7
#define CLK_BUS_R_CPUCFG 8
#endif /* _DT_BINDINGS_CLK_SUN20I_D1_R_CCU_H_ */

View File

@ -0,0 +1,77 @@
/* SPDX-License-Identifier: (GPL-2.0+ or MIT) */
/*
* Copyright (c) 2020 huangzhenwei@allwinnertech.com
* Copyright (C) 2021 Samuel Holland <samuel@sholland.org>
*/
#ifndef _DT_BINDINGS_RST_SUN20I_D1_CCU_H_
#define _DT_BINDINGS_RST_SUN20I_D1_CCU_H_
#define RST_MBUS 0
#define RST_BUS_DE 1
#define RST_BUS_DI 2
#define RST_BUS_G2D 3
#define RST_BUS_CE 4
#define RST_BUS_VE 5
#define RST_BUS_DMA 6
#define RST_BUS_MSGBOX0 7
#define RST_BUS_MSGBOX1 8
#define RST_BUS_MSGBOX2 9
#define RST_BUS_SPINLOCK 10
#define RST_BUS_HSTIMER 11
#define RST_BUS_DBG 12
#define RST_BUS_PWM 13
#define RST_BUS_DRAM 14
#define RST_BUS_MMC0 15
#define RST_BUS_MMC1 16
#define RST_BUS_MMC2 17
#define RST_BUS_UART0 18
#define RST_BUS_UART1 19
#define RST_BUS_UART2 20
#define RST_BUS_UART3 21
#define RST_BUS_UART4 22
#define RST_BUS_UART5 23
#define RST_BUS_I2C0 24
#define RST_BUS_I2C1 25
#define RST_BUS_I2C2 26
#define RST_BUS_I2C3 27
#define RST_BUS_SPI0 28
#define RST_BUS_SPI1 29
#define RST_BUS_EMAC 30
#define RST_BUS_IR_TX 31
#define RST_BUS_GPADC 32
#define RST_BUS_THS 33
#define RST_BUS_I2S0 34
#define RST_BUS_I2S1 35
#define RST_BUS_I2S2 36
#define RST_BUS_SPDIF 37
#define RST_BUS_DMIC 38
#define RST_BUS_AUDIO 39
#define RST_USB_PHY0 40
#define RST_USB_PHY1 41
#define RST_BUS_OHCI0 42
#define RST_BUS_OHCI1 43
#define RST_BUS_EHCI0 44
#define RST_BUS_EHCI1 45
#define RST_BUS_OTG 46
#define RST_BUS_LRADC 47
#define RST_BUS_DPSS_TOP 48
#define RST_BUS_HDMI_SUB 49
#define RST_BUS_HDMI_MAIN 50
#define RST_BUS_MIPI_DSI 51
#define RST_BUS_TCON_LCD0 52
#define RST_BUS_TCON_TV 53
#define RST_BUS_LVDS0 54
#define RST_BUS_TVE 55
#define RST_BUS_TVE_TOP 56
#define RST_BUS_TVD 57
#define RST_BUS_TVD_TOP 58
#define RST_BUS_LEDC 59
#define RST_BUS_CSI 60
#define RST_BUS_TPADC 61
#define RST_DSP 62
#define RST_BUS_DSP_CFG 63
#define RST_BUS_DSP_DBG 64
#define RST_BUS_RISCV_CFG 65
#endif /* _DT_BINDINGS_RST_SUN20I_D1_CCU_H_ */

View File

@ -0,0 +1,16 @@
/* SPDX-License-Identifier: (GPL-2.0+ or MIT) */
/*
* Copyright (C) 2021 Samuel Holland <samuel@sholland.org>
*/
#ifndef _DT_BINDINGS_RST_SUN20I_D1_R_CCU_H_
#define _DT_BINDINGS_RST_SUN20I_D1_R_CCU_H_
#define RST_BUS_R_TIMER 0
#define RST_BUS_R_TWD 1
#define RST_BUS_R_PPU 2
#define RST_BUS_R_IR_RX 3
#define RST_BUS_R_RTC 4
#define RST_BUS_R_CPUCFG 5
#endif /* _DT_BINDINGS_RST_SUN20I_D1_R_CCU_H_ */

View File

@ -6,22 +6,7 @@
#ifndef _LINUX_CLK_SUNXI_NG_H_ #ifndef _LINUX_CLK_SUNXI_NG_H_
#define _LINUX_CLK_SUNXI_NG_H_ #define _LINUX_CLK_SUNXI_NG_H_
#include <linux/errno.h>
#ifdef CONFIG_SUNXI_CCU
int sunxi_ccu_set_mmc_timing_mode(struct clk *clk, bool new_mode); int sunxi_ccu_set_mmc_timing_mode(struct clk *clk, bool new_mode);
int sunxi_ccu_get_mmc_timing_mode(struct clk *clk); int sunxi_ccu_get_mmc_timing_mode(struct clk *clk);
#else
static inline int sunxi_ccu_set_mmc_timing_mode(struct clk *clk,
bool new_mode)
{
return -ENOTSUPP;
}
static inline int sunxi_ccu_get_mmc_timing_mode(struct clk *clk)
{
return -ENOTSUPP;
}
#endif
#endif #endif

View File

@ -1025,8 +1025,9 @@ bool i2c_acpi_get_i2c_resource(struct acpi_resource *ares,
struct acpi_resource_i2c_serialbus **i2c); struct acpi_resource_i2c_serialbus **i2c);
int i2c_acpi_client_count(struct acpi_device *adev); int i2c_acpi_client_count(struct acpi_device *adev);
u32 i2c_acpi_find_bus_speed(struct device *dev); u32 i2c_acpi_find_bus_speed(struct device *dev);
struct i2c_client *i2c_acpi_new_device(struct device *dev, int index, struct i2c_client *i2c_acpi_new_device_by_fwnode(struct fwnode_handle *fwnode,
struct i2c_board_info *info); int index,
struct i2c_board_info *info);
struct i2c_adapter *i2c_acpi_find_adapter_by_handle(acpi_handle handle); struct i2c_adapter *i2c_acpi_find_adapter_by_handle(acpi_handle handle);
bool i2c_acpi_waive_d0_probe(struct device *dev); bool i2c_acpi_waive_d0_probe(struct device *dev);
#else #else
@ -1043,8 +1044,9 @@ static inline u32 i2c_acpi_find_bus_speed(struct device *dev)
{ {
return 0; return 0;
} }
static inline struct i2c_client *i2c_acpi_new_device(struct device *dev, static inline struct i2c_client *i2c_acpi_new_device_by_fwnode(
int index, struct i2c_board_info *info) struct fwnode_handle *fwnode, int index,
struct i2c_board_info *info)
{ {
return ERR_PTR(-ENODEV); return ERR_PTR(-ENODEV);
} }
@ -1058,4 +1060,11 @@ static inline bool i2c_acpi_waive_d0_probe(struct device *dev)
} }
#endif /* CONFIG_ACPI */ #endif /* CONFIG_ACPI */
static inline struct i2c_client *i2c_acpi_new_device(struct device *dev,
int index,
struct i2c_board_info *info)
{
return i2c_acpi_new_device_by_fwnode(dev_fwnode(dev), index, info);
}
#endif /* _LINUX_I2C_H */ #endif /* _LINUX_I2C_H */

View File

@ -75,6 +75,17 @@
#define TPS68470_CLKCFG1_MODE_A_MASK GENMASK(1, 0) #define TPS68470_CLKCFG1_MODE_A_MASK GENMASK(1, 0)
#define TPS68470_CLKCFG1_MODE_B_MASK GENMASK(3, 2) #define TPS68470_CLKCFG1_MODE_B_MASK GENMASK(3, 2)
#define TPS68470_CLKCFG2_DRV_STR_2MA 0x05
#define TPS68470_PLL_OUTPUT_ENABLE 0x02
#define TPS68470_CLK_SRC_XTAL BIT(0)
#define TPS68470_PLLSWR_DEFAULT GENMASK(1, 0)
#define TPS68470_OSC_EXT_CAP_DEFAULT 0x05
#define TPS68470_OUTPUT_A_SHIFT 0x00
#define TPS68470_OUTPUT_B_SHIFT 0x02
#define TPS68470_CLK_SRC_SHIFT GENMASK(2, 0)
#define TPS68470_OSC_EXT_CAP_SHIFT BIT(2)
#define TPS68470_GPIO_CTL_REG_A(x) (TPS68470_REG_GPCTL0A + (x) * 2) #define TPS68470_GPIO_CTL_REG_A(x) (TPS68470_REG_GPCTL0A + (x) * 2)
#define TPS68470_GPIO_CTL_REG_B(x) (TPS68470_REG_GPCTL0B + (x) * 2) #define TPS68470_GPIO_CTL_REG_B(x) (TPS68470_REG_GPCTL0B + (x) * 2)
#define TPS68470_GPIO_MODE_MASK GENMASK(1, 0) #define TPS68470_GPIO_MODE_MASK GENMASK(1, 0)

View File

@ -12,7 +12,7 @@
struct fch_clk_data { struct fch_clk_data {
void __iomem *base; void __iomem *base;
u32 is_rv; char *name;
}; };
#endif /* __CLK_FCH_H */ #endif /* __CLK_FCH_H */

View File

@ -0,0 +1,35 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* TI TPS68470 PMIC platform data definition.
*
* Copyright (c) 2021 Red Hat Inc.
*
* Red Hat authors:
* Hans de Goede <hdegoede@redhat.com>
*/
#ifndef __PDATA_TPS68470_H
#define __PDATA_TPS68470_H
enum tps68470_regulators {
TPS68470_CORE,
TPS68470_ANA,
TPS68470_VCM,
TPS68470_VIO,
TPS68470_VSIO,
TPS68470_AUX1,
TPS68470_AUX2,
TPS68470_NUM_REGULATORS
};
struct regulator_init_data;
struct tps68470_regulator_platform_data {
const struct regulator_init_data *reg_init_data[TPS68470_NUM_REGULATORS];
};
struct tps68470_clk_platform_data {
const char *consumer_dev_name;
const char *consumer_con_id;
};
#endif