Commit 5011bb9f authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'arm-soc-v5.12' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc

Pull ARM SoC updates from Arnd Bergmann:
 "This is mostly 32-bit code for SoC platforms, and looks smaller than
  any such branch I remember from previous kernels, as most of this is
  now handled in other subsystems for modern platforms:

   - Minor bugfixes and Kconfig updates for Tegra, Broadcom, i.MX,
     Renesas, and Samsung

   - Updates to the MAINTAINERS listing for Actions, OMAP, and Samsung

   - Samsung SoC driver updates to make them loadable modules"

* tag 'arm-soc-v5.12' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc:
  MAINTAINERS: arm: samsung: include S3C headers in platform entry
  MAINTAINERS: Add linux-actions ML for Actions Semi Arch
  ARM: s3c: irq-s3c24xx: staticize local functions
  ARM: s3c: irq-s3c24xx: include headers for missing declarations
  ARM: s3c: fix fiq for clang IAS
  ARM: imx: Remove unused IMX_GPIO_NR() macro
  soc: renesas: rcar-sysc: Mark device node OF_POPULATED after init
  ARM: OMAP2+: fix spellint typo
  MAINTAINERS: Update address for OMAP GPMC driver
  soc: renesas: rcar-sysc: Use readl_poll_timeout_atomic()
  ARM: bcm: Select BRCMSTB_L2_IRQ for bcm2835
  ARM: brcmstb: Add debug UART entry for 72116
  ARM: tegra: Don't enable unused PLLs on resume from suspend
  soc: samsung: pm_domains: Convert to regular platform driver
  soc: samsung: exynos-chipid: correct helpers __init annotation
  ARM: mach-imx: imx6ul: Print SOC revision on boot
  ARM: imx: mach-imx6ul: remove 14x14 EVK specific PHY fixup
  soc: samsung: exynos-chipid: convert to driver and merge exynos-asv
  soc: samsung: exynos-asv: handle reading revision register error
  soc: samsung: exynos-asv: don't defer early on not-supported SoCs
parents 584ce3c9 c2bd78de
......@@ -1511,6 +1511,7 @@ ARM/ACTIONS SEMI ARCHITECTURE
M: Andreas Färber <afaerber@suse.de>
M: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
L: linux-actions@lists.infradead.org (moderated for non-subscribers)
S: Maintained
F: Documentation/devicetree/bindings/arm/actions.yaml
F: Documentation/devicetree/bindings/clock/actions,owl-cmu.txt
......@@ -2382,6 +2383,8 @@ F: drivers/*/*s5pv210*
F: drivers/memory/samsung/
F: drivers/soc/samsung/
F: drivers/tty/serial/samsung*
F: include/linux/platform_data/*s3c*
F: include/linux/serial_s3c.h
F: include/linux/soc/samsung/
N: exynos
N: s3c2410
......@@ -12843,7 +12846,7 @@ S: Orphan
F: drivers/video/fbdev/omap/
OMAP GENERAL PURPOSE MEMORY CONTROLLER SUPPORT
M: Roger Quadros <rogerq@ti.com>
M: Roger Quadros <rogerq@kernel.org>
M: Tony Lindgren <tony@atomide.com>
L: linux-omap@vger.kernel.org
S: Maintained
......
......@@ -25,6 +25,7 @@
#define SUN_TOP_CTRL_BASE_V7 REG_PHYS_ADDR_V7(0x404000)
#define UARTA_3390 REG_PHYS_ADDR(0x40a900)
#define UARTA_72116 UARTA_7255
#define UARTA_7250 REG_PHYS_ADDR(0x40b400)
#define UARTA_7255 REG_PHYS_ADDR(0x40c000)
#define UARTA_7260 UARTA_7255
......@@ -85,20 +86,21 @@ ARM_BE8( rev \rv, \rv )
/* Chip specific detection starts here */
20: checkuart(\rp, \rv, 0x33900000, 3390)
21: checkuart(\rp, \rv, 0x72160000, 7216)
22: checkuart(\rp, \rv, 0x07216400, 72164)
23: checkuart(\rp, \rv, 0x07216500, 72165)
24: checkuart(\rp, \rv, 0x72500000, 7250)
25: checkuart(\rp, \rv, 0x72550000, 7255)
26: checkuart(\rp, \rv, 0x72600000, 7260)
27: checkuart(\rp, \rv, 0x72680000, 7268)
28: checkuart(\rp, \rv, 0x72710000, 7271)
29: checkuart(\rp, \rv, 0x72780000, 7278)
30: checkuart(\rp, \rv, 0x73640000, 7364)
31: checkuart(\rp, \rv, 0x73660000, 7366)
32: checkuart(\rp, \rv, 0x07437100, 74371)
33: checkuart(\rp, \rv, 0x74390000, 7439)
34: checkuart(\rp, \rv, 0x74450000, 7445)
21: checkuart(\rp, \rv, 0x07211600, 72116)
22: checkuart(\rp, \rv, 0x72160000, 7216)
23: checkuart(\rp, \rv, 0x07216400, 72164)
24: checkuart(\rp, \rv, 0x07216500, 72165)
25: checkuart(\rp, \rv, 0x72500000, 7250)
26: checkuart(\rp, \rv, 0x72550000, 7255)
27: checkuart(\rp, \rv, 0x72600000, 7260)
28: checkuart(\rp, \rv, 0x72680000, 7268)
29: checkuart(\rp, \rv, 0x72710000, 7271)
30: checkuart(\rp, \rv, 0x72780000, 7278)
31: checkuart(\rp, \rv, 0x73640000, 7364)
32: checkuart(\rp, \rv, 0x73660000, 7366)
33: checkuart(\rp, \rv, 0x07437100, 74371)
34: checkuart(\rp, \rv, 0x74390000, 7439)
35: checkuart(\rp, \rv, 0x74450000, 7445)
/* No valid UART found */
90: mov \rp, #0
......
......@@ -161,6 +161,7 @@ config ARCH_BCM2835
select ARM_TIMER_SP804
select HAVE_ARM_ARCH_TIMER if ARCH_MULTI_V7
select BCM2835_TIMER
select BRCMSTB_L2_IRQ
select PINCTRL
select PINCTRL_BCM2835
select MFD_CORE
......
......@@ -13,7 +13,6 @@ menuconfig ARCH_EXYNOS
select ARM_GIC
select EXYNOS_IRQ_COMBINER
select COMMON_CLK_SAMSUNG
select EXYNOS_ASV
select EXYNOS_CHIPID
select EXYNOS_THERMAL
select EXYNOS_PMU
......
......@@ -106,8 +106,4 @@
.type = _type, \
}
/* There's an off-by-one between the gpio bank number and the gpiochip */
/* range e.g. GPIO_1_5 is gpio 5 under linux */
#define IMX_GPIO_NR(bank, nr) (((bank) - 1) * 32 + (nr))
#endif /* __ASM_ARCH_MXC_HARDWARE_H__ */
......@@ -14,6 +14,7 @@
#include "common.h"
#include "cpuidle.h"
#include "hardware.h"
static void __init imx6ul_enet_clk_init(void)
{
......@@ -27,34 +28,16 @@ static void __init imx6ul_enet_clk_init(void)
pr_err("failed to find fsl,imx6ul-iomux-gpr regmap\n");
}
static int ksz8081_phy_fixup(struct phy_device *dev)
{
if (dev && dev->interface == PHY_INTERFACE_MODE_MII) {
phy_write(dev, 0x1f, 0x8110);
phy_write(dev, 0x16, 0x201);
} else if (dev && dev->interface == PHY_INTERFACE_MODE_RMII) {
phy_write(dev, 0x1f, 0x8190);
phy_write(dev, 0x16, 0x202);
}
return 0;
}
static void __init imx6ul_enet_phy_init(void)
{
if (IS_BUILTIN(CONFIG_PHYLIB))
phy_register_fixup_for_uid(PHY_ID_KSZ8081, MICREL_PHY_ID_MASK,
ksz8081_phy_fixup);
}
static inline void imx6ul_enet_init(void)
{
imx6ul_enet_clk_init();
imx6ul_enet_phy_init();
}
static void __init imx6ul_init_machine(void)
{
imx_print_silicon_rev(cpu_is_imx6ull() ? "i.MX6ULL" : "i.MX6UL",
imx_get_soc_revision());
of_platform_default_populate(NULL, NULL, NULL);
imx6ul_enet_init();
imx_anatop_init();
......
......@@ -1299,7 +1299,7 @@ int clkdm_hwmod_disable(struct clockdomain *clkdm, struct omap_hwmod *oh)
* Due to a suspend or hibernation operation, the state of the registers
* controlling this clkdm will be lost, save their context.
*/
static int _clkdm_save_context(struct clockdomain *clkdm, void *ununsed)
static int _clkdm_save_context(struct clockdomain *clkdm, void *unused)
{
if (!arch_clkdm || !arch_clkdm->clkdm_save_context)
return -EINVAL;
......@@ -1312,7 +1312,7 @@ static int _clkdm_save_context(struct clockdomain *clkdm, void *ununsed)
*
* Restore the register values for this clockdomain.
*/
static int _clkdm_restore_context(struct clockdomain *clkdm, void *ununsed)
static int _clkdm_restore_context(struct clockdomain *clkdm, void *unused)
{
if (!arch_clkdm || !arch_clkdm->clkdm_restore_context)
return -EINVAL;
......
......@@ -35,7 +35,6 @@
@ and an offset to the irq acknowledgment word
ENTRY(s3c24xx_spi_fiq_rx)
s3c24xx_spi_fix_rx:
.word fiq_rx_end - fiq_rx_start
.word fiq_rx_irq_ack - fiq_rx_start
fiq_rx_start:
......@@ -49,7 +48,7 @@ fiq_rx_start:
strb fiq_rtmp, [ fiq_rspi, # S3C2410_SPTDAT ]
subs fiq_rcount, fiq_rcount, #1
subnes pc, lr, #4 @@ return, still have work to do
subsne pc, lr, #4 @@ return, still have work to do
@@ set IRQ controller so that next op will trigger IRQ
mov fiq_rtmp, #0
......@@ -61,7 +60,6 @@ fiq_rx_irq_ack:
fiq_rx_end:
ENTRY(s3c24xx_spi_fiq_txrx)
s3c24xx_spi_fiq_txrx:
.word fiq_txrx_end - fiq_txrx_start
.word fiq_txrx_irq_ack - fiq_txrx_start
fiq_txrx_start:
......@@ -76,7 +74,7 @@ fiq_txrx_start:
strb fiq_rtmp, [ fiq_rspi, # S3C2410_SPTDAT ]
subs fiq_rcount, fiq_rcount, #1
subnes pc, lr, #4 @@ return, still have work to do
subsne pc, lr, #4 @@ return, still have work to do
mov fiq_rtmp, #0
str fiq_rtmp, [ fiq_rirq, # S3C2410_INTMOD - S3C24XX_VA_IRQ ]
......@@ -88,7 +86,6 @@ fiq_txrx_irq_ack:
fiq_txrx_end:
ENTRY(s3c24xx_spi_fiq_tx)
s3c24xx_spi_fix_tx:
.word fiq_tx_end - fiq_tx_start
.word fiq_tx_irq_ack - fiq_tx_start
fiq_tx_start:
......@@ -101,7 +98,7 @@ fiq_tx_start:
strb fiq_rtmp, [ fiq_rspi, # S3C2410_SPTDAT ]
subs fiq_rcount, fiq_rcount, #1
subnes pc, lr, #4 @@ return, still have work to do
subsne pc, lr, #4 @@ return, still have work to do
mov fiq_rtmp, #0
str fiq_rtmp, [ fiq_rirq, # S3C2410_INTMOD - S3C24XX_VA_IRQ ]
......
......@@ -21,6 +21,7 @@
#include <linux/of.h>
#include <linux/of_irq.h>
#include <linux/of_address.h>
#include <linux/spi/s3c24xx.h>
#include <asm/exception.h>
#include <asm/mach/irq.h>
......@@ -32,6 +33,7 @@
#include "cpu.h"
#include "regs-irqtype.h"
#include "pm.h"
#include "s3c24xx.h"
#define S3C_IRQTYPE_NONE 0
#define S3C_IRQTYPE_EINT 1
......@@ -357,7 +359,7 @@ static inline int s3c24xx_handle_intc(struct s3c_irq_intc *intc,
return true;
}
asmlinkage void __exception_irq_entry s3c24xx_handle_irq(struct pt_regs *regs)
static asmlinkage void __exception_irq_entry s3c24xx_handle_irq(struct pt_regs *regs)
{
do {
if (likely(s3c_intc[0]))
......@@ -1305,7 +1307,7 @@ static struct s3c24xx_irq_of_ctrl s3c2410_ctrl[] = {
}
};
int __init s3c2410_init_intc_of(struct device_node *np,
static int __init s3c2410_init_intc_of(struct device_node *np,
struct device_node *interrupt_parent)
{
return s3c_init_intc_of(np, interrupt_parent,
......@@ -1327,7 +1329,7 @@ static struct s3c24xx_irq_of_ctrl s3c2416_ctrl[] = {
}
};
int __init s3c2416_init_intc_of(struct device_node *np,
static int __init s3c2416_init_intc_of(struct device_node *np,
struct device_node *interrupt_parent)
{
return s3c_init_intc_of(np, interrupt_parent,
......
......@@ -43,11 +43,34 @@
#define APB_MISC_XM2CFGCPADCTRL2 0x8e4
#define APB_MISC_XM2CFGDPADCTRL2 0x8e8
.macro pll_enable, rd, r_car_base, pll_base
#define PLLC_STORE_MASK (1 << 0)
#define PLLM_STORE_MASK (1 << 1)
#define PLLP_STORE_MASK (1 << 2)
.macro test_pll_state, rd, test_mask
ldr \rd, tegra_pll_state
tst \rd, #\test_mask
.endm
.macro store_pll_state, rd, tmp, r_car_base, pll_base, pll_mask
ldr \rd, [\r_car_base, #\pll_base]
tst \rd, #(1 << 30)
ldr \rd, tegra_pll_state
biceq \rd, \rd, #\pll_mask
orrne \rd, \rd, #\pll_mask
adr \tmp, tegra_pll_state
str \rd, [\tmp]
.endm
.macro pll_enable, rd, r_car_base, pll_base, test_mask
test_pll_state \rd, \test_mask
beq 1f
ldr \rd, [\r_car_base, #\pll_base]
tst \rd, #(1 << 30)
orreq \rd, \rd, #(1 << 30)
streq \rd, [\r_car_base, #\pll_base]
1:
.endm
.macro emc_device_mask, rd, base
......@@ -177,9 +200,9 @@ ENTRY(tegra20_lp1_reset)
str r1, [r0, #CLK_RESET_CCLK_DIVIDER]
str r1, [r0, #CLK_RESET_SCLK_DIVIDER]
pll_enable r1, r0, CLK_RESET_PLLM_BASE
pll_enable r1, r0, CLK_RESET_PLLP_BASE
pll_enable r1, r0, CLK_RESET_PLLC_BASE
pll_enable r1, r0, CLK_RESET_PLLM_BASE, PLLM_STORE_MASK
pll_enable r1, r0, CLK_RESET_PLLP_BASE, PLLP_STORE_MASK
pll_enable r1, r0, CLK_RESET_PLLC_BASE, PLLC_STORE_MASK
adr r2, tegra20_sdram_pad_address
adr r4, tegra20_sdram_pad_save
......@@ -270,6 +293,10 @@ tegra20_switch_cpu_to_clk32k:
add r1, r1, #2
wait_until r1, r7, r9
store_pll_state r0, r1, r5, CLK_RESET_PLLC_BASE, PLLC_STORE_MASK
store_pll_state r0, r1, r5, CLK_RESET_PLLM_BASE, PLLM_STORE_MASK
store_pll_state r0, r1, r5, CLK_RESET_PLLP_BASE, PLLP_STORE_MASK
/* disable PLLM, PLLP and PLLC */
ldr r0, [r5, #CLK_RESET_PLLM_BASE]
bic r0, r0, #(1 << 30)
......@@ -396,6 +423,9 @@ tegra20_sdram_pad_save:
.long 0
.endr
tegra_pll_state:
.word 0x0
.ltorg
/* dummy symbol for end of IRAM */
.align L1_CACHE_SHIFT
......
......@@ -71,6 +71,13 @@
#define TEGRA30_POWER_HOTPLUG_SHUTDOWN (1 << 27) /* Hotplug shutdown */
#define PLLA_STORE_MASK (1 << 0)
#define PLLC_STORE_MASK (1 << 1)
#define PLLM_STORE_MASK (1 << 2)
#define PLLP_STORE_MASK (1 << 3)
#define PLLX_STORE_MASK (1 << 4)
#define PLLM_PMC_STORE_MASK (1 << 5)
.macro emc_device_mask, rd, base
ldr \rd, [\base, #EMC_ADR_CFG]
tst \rd, #0x1
......@@ -87,7 +94,43 @@
bne 1001b
.endm
.macro pll_enable, rd, r_car_base, pll_base, pll_misc
.macro test_pll_state, rd, test_mask
ldr \rd, tegra_pll_state
tst \rd, #\test_mask
.endm
.macro store_pll_state, rd, tmp, r_car_base, pll_base, pll_mask
ldr \rd, [\r_car_base, #\pll_base]
tst \rd, #(1 << 30)
ldr \rd, tegra_pll_state
biceq \rd, \rd, #\pll_mask
orrne \rd, \rd, #\pll_mask
adr \tmp, tegra_pll_state
str \rd, [\tmp]
.endm
.macro store_pllm_pmc_state, rd, tmp, pmc_base
ldr \rd, [\pmc_base, #PMC_PLLP_WB0_OVERRIDE]
tst \rd, #(1 << 12)
ldr \rd, tegra_pll_state
biceq \rd, \rd, #PLLM_PMC_STORE_MASK
orrne \rd, \rd, #PLLM_PMC_STORE_MASK
adr \tmp, tegra_pll_state
str \rd, [\tmp]
.endm
.macro pllm_pmc_enable, rd, pmc_base
test_pll_state \rd, PLLM_PMC_STORE_MASK
ldrne \rd, [\pmc_base, #PMC_PLLP_WB0_OVERRIDE]
orrne \rd, \rd, #(1 << 12)
strne \rd, [\pmc_base, #PMC_PLLP_WB0_OVERRIDE]
.endm
.macro pll_enable, rd, r_car_base, pll_base, pll_misc, test_mask
test_pll_state \rd, \test_mask
beq 1f
ldr \rd, [\r_car_base, #\pll_base]
tst \rd, #(1 << 30)
orreq \rd, \rd, #(1 << 30)
......@@ -102,13 +145,17 @@
orr \rd, \rd, #(1 << 18)
str \rd, [\r_car_base, #\pll_misc]
.endif
1:
.endm
.macro pll_locked, rd, r_car_base, pll_base
.macro pll_locked, rd, r_car_base, pll_base, test_mask
test_pll_state \rd, \test_mask
beq 2f
1:
ldr \rd, [\r_car_base, #\pll_base]
tst \rd, #(1 << 27)
beq 1b
2:
.endm
.macro pll_iddq_exit, rd, car, iddq, iddq_bit
......@@ -342,34 +389,30 @@ ENTRY(tegra30_lp1_reset)
/* enable PLLM via PMC */
mov32 r2, TEGRA_PMC_BASE
ldr r1, [r2, #PMC_PLLP_WB0_OVERRIDE]
orr r1, r1, #(1 << 12)
str r1, [r2, #PMC_PLLP_WB0_OVERRIDE]
pllm_pmc_enable r1, r2
pll_enable r1, r0, CLK_RESET_PLLM_BASE, 0
pll_enable r1, r0, CLK_RESET_PLLC_BASE, 0
pll_enable r1, r0, CLK_RESET_PLLX_BASE, 0
pll_enable r1, r0, CLK_RESET_PLLM_BASE, 0, PLLM_STORE_MASK
pll_enable r1, r0, CLK_RESET_PLLC_BASE, 0, PLLC_STORE_MASK
pll_enable r1, r0, CLK_RESET_PLLX_BASE, 0, PLLX_STORE_MASK
b _pll_m_c_x_done
_no_pll_iddq_exit:
/* enable PLLM via PMC */
mov32 r2, TEGRA_PMC_BASE
ldr r1, [r2, #PMC_PLLP_WB0_OVERRIDE]
orr r1, r1, #(1 << 12)
str r1, [r2, #PMC_PLLP_WB0_OVERRIDE]
pllm_pmc_enable r1, r2
pll_enable r1, r0, CLK_RESET_PLLM_BASE, CLK_RESET_PLLM_MISC
pll_enable r1, r0, CLK_RESET_PLLC_BASE, CLK_RESET_PLLC_MISC
pll_enable r1, r0, CLK_RESET_PLLM_BASE, CLK_RESET_PLLM_MISC, PLLM_STORE_MASK
pll_enable r1, r0, CLK_RESET_PLLC_BASE, CLK_RESET_PLLC_MISC, PLLC_STORE_MASK
_pll_m_c_x_done:
pll_enable r1, r0, CLK_RESET_PLLP_BASE, CLK_RESET_PLLP_MISC
pll_enable r1, r0, CLK_RESET_PLLA_BASE, CLK_RESET_PLLA_MISC
pll_enable r1, r0, CLK_RESET_PLLP_BASE, CLK_RESET_PLLP_MISC, PLLP_STORE_MASK
pll_enable r1, r0, CLK_RESET_PLLA_BASE, CLK_RESET_PLLA_MISC, PLLA_STORE_MASK
pll_locked r1, r0, CLK_RESET_PLLM_BASE
pll_locked r1, r0, CLK_RESET_PLLP_BASE
pll_locked r1, r0, CLK_RESET_PLLA_BASE
pll_locked r1, r0, CLK_RESET_PLLC_BASE
pll_locked r1, r0, CLK_RESET_PLLM_BASE, PLLM_STORE_MASK
pll_locked r1, r0, CLK_RESET_PLLP_BASE, PLLP_STORE_MASK
pll_locked r1, r0, CLK_RESET_PLLA_BASE, PLLA_STORE_MASK
pll_locked r1, r0, CLK_RESET_PLLC_BASE, PLLC_STORE_MASK
/*
* CPUFreq driver could select other PLL for CPU. PLLX will be
......@@ -380,7 +423,7 @@ _pll_m_c_x_done:
cmp r1, #TEGRA30
beq 1f
pll_locked r1, r0, CLK_RESET_PLLX_BASE
pll_locked r1, r0, CLK_RESET_PLLX_BASE, PLLX_STORE_MASK
ldr r1, [r0, #CLK_RESET_PLLP_BASE]
bic r1, r1, #(1<<31) @ disable PllP bypass
......@@ -593,6 +636,9 @@ tegra_sdram_pad_save:
.long 0
.endr
tegra_pll_state:
.word 0x0
/*
* tegra30_tear_down_core
*
......@@ -641,6 +687,14 @@ tegra30_switch_cpu_to_clk32k:
add r1, r1, #2
wait_until r1, r7, r9
/* store enable-state of PLLs */
store_pll_state r0, r1, r5, CLK_RESET_PLLA_BASE, PLLA_STORE_MASK
store_pll_state r0, r1, r5, CLK_RESET_PLLC_BASE, PLLC_STORE_MASK
store_pll_state r0, r1, r5, CLK_RESET_PLLM_BASE, PLLM_STORE_MASK
store_pll_state r0, r1, r5, CLK_RESET_PLLP_BASE, PLLP_STORE_MASK
store_pll_state r0, r1, r5, CLK_RESET_PLLX_BASE, PLLX_STORE_MASK
store_pllm_pmc_state r0, r1, r4
/* disable PLLM via PMC in LP1 */
ldr r0, [r4, #PMC_PLLP_WB0_OVERRIDE]
bic r0, r0, #(1 << 12)
......
......@@ -39,6 +39,7 @@ config ARCH_BCM2835
select ARM_AMBA
select ARM_GIC
select ARM_TIMER_SP804
select BRCMSTB_L2_IRQ
help
This enables support for the Broadcom BCM2837 and BCM2711 SoC.
These SoCs are used in the Raspberry Pi 3 and 4 devices.
......
......@@ -15,6 +15,7 @@
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/io.h>
#include <linux/iopoll.h>
#include <linux/soc/renesas/rcar-sysc.h>
#include "rcar-sysc.h"
......@@ -44,13 +45,13 @@
#define PWRER_OFFS 0x14 /* Power Shutoff/Resume Error */
#define SYSCSR_RETRIES 100
#define SYSCSR_TIMEOUT 100
#define SYSCSR_DELAY_US 1
#define PWRER_RETRIES 100
#define PWRER_DELAY_US 1
#define SYSCISR_RETRIES 1000
#define SYSCISR_TIMEOUT 1000
#define SYSCISR_DELAY_US 1
#define RCAR_PD_ALWAYS_ON 32 /* Always-on power area */
......@@ -68,7 +69,8 @@ static u32 rcar_sysc_extmask_offs, rcar_sysc_extmask_val;
static int rcar_sysc_pwr_on_off(const struct rcar_sysc_ch *sysc_ch, bool on)
{
unsigned int sr_bit, reg_offs;
int k;
u32 val;
int ret;
if (on) {
sr_bit = SYSCSR_PONENB;
......@@ -79,13 +81,10 @@ static int rcar_sysc_pwr_on_off(const struct rcar_sysc_ch *sysc_ch, bool on)
}
/* Wait until SYSC is ready to accept a power request */
for (k = 0; k < SYSCSR_RETRIES; k++) {
if (ioread32(rcar_sysc_base + SYSCSR) & BIT(sr_bit))
break;
udelay(SYSCSR_DELAY_US);
}
if (k == SYSCSR_RETRIES)
ret = readl_poll_timeout_atomic(rcar_sysc_base + SYSCSR, val,
val & BIT(sr_bit), SYSCSR_DELAY_US,
SYSCSR_TIMEOUT);
if (ret)
return -EAGAIN;
/* Submit power shutoff or power resume request */
......@@ -99,10 +98,9 @@ static int rcar_sysc_power(const struct rcar_sysc_ch *sysc_ch, bool on)
{
unsigned int isr_mask = BIT(sysc_ch->isr_bit);
unsigned int chan_mask = BIT(sysc_ch->chan_bit);
unsigned int status;
unsigned int status, k;
unsigned long flags;
int ret = 0;
int k;
int ret;
spin_lock_irqsave(&rcar_sysc_lock, flags);
......@@ -145,13 +143,10 @@ static int rcar_sysc_power(const struct rcar_sysc_ch *sysc_ch, bool on)
}
/* Wait until the power shutoff or resume request has completed * */
for (k = 0; k < SYSCISR_RETRIES; k++) {
if (ioread32(rcar_sysc_base + SYSCISR) & isr_mask)
break;
udelay(SYSCISR_DELAY_US);
}
if (k == SYSCISR_RETRIES)
ret = readl_poll_timeout_atomic(rcar_sysc_base + SYSCISR, status,
status & isr_mask, SYSCISR_DELAY_US,
SYSCISR_TIMEOUT);
if (ret)
ret = -EIO;
iowrite32(isr_mask, rcar_sysc_base + SYSCISCR);
......@@ -439,6 +434,8 @@ static int __init rcar_sysc_pd_init(void)
}
error = of_genpd_add_provider_onecell(np, &domains->onecell_data);
if (!error)
of_node_set_flag(np, OF_POPULATED);
out_put:
of_node_put(np);
......
......@@ -7,21 +7,19 @@ menuconfig SOC_SAMSUNG
if SOC_SAMSUNG
config EXYNOS_ASV
bool "Exynos Adaptive Supply Voltage support" if COMPILE_TEST
depends on (ARCH_EXYNOS && EXYNOS_CHIPID) || COMPILE_TEST
select EXYNOS_ASV_ARM if ARM && ARCH_EXYNOS
# There is no need to enable these drivers for ARMv8
config EXYNOS_ASV_ARM
bool "Exynos ASV ARMv7-specific driver extensions" if COMPILE_TEST
depends on EXYNOS_ASV
depends on EXYNOS_CHIPID
config EXYNOS_CHIPID
bool "Exynos Chipid controller driver" if COMPILE_TEST
bool "Exynos ChipID controller and ASV driver" if COMPILE_TEST
depends on ARCH_EXYNOS || COMPILE_TEST
select EXYNOS_ASV_ARM if ARM && ARCH_EXYNOS
select MFD_SYSCON
select SOC_BUS
help
Support for Samsung Exynos SoC ChipID and Adaptive Supply Voltage.
config EXYNOS_PMU
bool "Exynos PMU controller driver" if COMPILE_TEST
......
# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_EXYNOS_ASV) += exynos-asv.o
obj-$(CONFIG_EXYNOS_ASV_ARM) += exynos5422-asv.o
obj-$(CONFIG_EXYNOS_CHIPID) += exynos-chipid.o
obj-$(CONFIG_EXYNOS_CHIPID) += exynos-chipid.o exynos-asv.o
obj-$(CONFIG_EXYNOS_PMU) += exynos-pmu.o
obj-$(CONFIG_EXYNOS_PMU_ARM_DRIVERS) += exynos3250-pmu.o exynos4-pmu.o \
......
......@@ -2,7 +2,9 @@
/*
* Copyright (c) 2019 Samsung Electronics Co., Ltd.
* http://www.samsung.com/
* Copyright (c) 2020 Krzysztof Kozlowski <krzk@kernel.org>
* Author: Sylwester Nawrocki <s.nawrocki@samsung.com>
* Author: Krzysztof Kozlowski <krzk@kernel.org>
*
* Samsung Exynos SoC Adaptive Supply Voltage support
*/
......@@ -10,12 +12,7 @@
#include <linux/cpu.h>
#include <linux/device.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/mfd/syscon.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/pm_opp.h>
#include <linux/regmap.h>
#include <linux/soc/samsung/exynos-chipid.h>
......@@ -111,7 +108,7 @@ static int exynos_asv_update_opps(struct exynos_asv *asv)
return 0;
}
static int exynos_asv_probe(struct platform_device *pdev)
int exynos_asv_init(struct device *dev, struct regmap *regmap)
{
int (*probe_func)(struct exynos_asv *asv);
struct exynos_asv *asv;
......@@ -119,39 +116,39 @@ static int exynos_asv_probe(struct platform_device *pdev)
u32 product_id = 0;
int ret, i;
cpu_dev = get_cpu_device(0);
ret = dev_pm_opp_get_opp_count(cpu_dev);
if (ret < 0)
return -EPROBE_DEFER;
asv = devm_kzalloc(&pdev->dev, sizeof(*asv), GFP_KERNEL);
asv = devm_kzalloc(dev, sizeof(*asv), GFP_KERNEL);
if (!asv)
return -ENOMEM;
asv->chipid_regmap = device_node_to_regmap(pdev->dev.of_node);
if (IS_ERR(asv->chipid_regmap)) {
dev_err(&pdev->dev, "Could not find syscon regmap\n");
return PTR_ERR(asv->chipid_regmap);
asv->chipid_regmap = regmap;
asv->dev = dev;
ret = regmap_read(asv->chipid_regmap, EXYNOS_CHIPID_REG_PRO_ID,
&product_id);
if (ret < 0) {
dev_err(dev, "Cannot read revision from ChipID: %d\n", ret);
return -ENODEV;
}
regmap_read(asv->chipid_regmap, EXYNOS_CHIPID_REG_PRO_ID, &product_id);
switch (product_id & EXYNOS_MASK) {
case 0xE5422000:
probe_func = exynos5422_asv_init;
break;
default:
return -ENODEV;
dev_dbg(dev, "No ASV support for this SoC\n");
devm_kfree(dev, asv);
return 0;
}
ret = of_property_read_u32(pdev->dev.of_node, "samsung,asv-bin",
cpu_dev = get_cpu_device(0);
ret = dev_pm_opp_get_opp_count(cpu_dev);
if (ret < 0)
return -EPROBE_DEFER;
ret = of_property_read_u32(dev->of_node, "samsung,asv-bin",
&asv->of_bin);
if (ret < 0)
asv->of_bin = -EINVAL;
asv->dev = &pdev->dev;
dev_set_drvdata(&pdev->dev, asv);
for (i = 0; i < ARRAY_SIZE(asv->subsys); i++)
asv->subsys[i].asv = asv;
......@@ -161,17 +158,3 @@ static int exynos_asv_probe(struct platform_device *pdev)
return exynos_asv_update_opps(asv);
}
static const struct of_device_id exynos_asv_of_device_ids[] = {
{ .compatible = "samsung,exynos4210-chipid" },
{}
};
static struct platform_driver exynos_asv_driver = {
.driver = {
.name = "exynos-asv",
.of_match_table = exynos_asv_of_device_ids,
},
.probe = exynos_asv_probe,
};
module_platform_driver(exynos_asv_driver);
......@@ -68,4 +68,6 @@ static inline u32 exynos_asv_opp_get_frequency(const struct exynos_asv_subsys *s
return __asv_get_table_entry(&subsys->table, level, 0);
}
int exynos_asv_init(struct device *dev, struct regmap *regmap);
#endif /* __LINUX_SOC_EXYNOS_ASV_H */
......@@ -2,20 +2,28 @@
/*
* Copyright (c) 2019 Samsung Electronics Co., Ltd.
* http://www.samsung.com/
* Copyright (c) 2020 Krzysztof Kozlowski <krzk@kernel.org>
*
* Exynos - CHIP ID support
* Author: Pankaj Dubey <pankaj.dubey@samsung.com>
* Author: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
* Author: Krzysztof Kozlowski <krzk@kernel.org>
*
* Samsung Exynos SoC Adaptive Supply Voltage and Chip ID support
*/
#include <linux/io.h>
#include <linux/device.h>
#include <linux/errno.h>
#include <linux/mfd/syscon.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/slab.h>
#include <linux/soc/samsung/exynos-chipid.h>
#include <linux/sys_soc.h>
#include "exynos-asv.h"
static const struct exynos_soc_id {
const char *name;
unsigned int id;
......@@ -36,7 +44,7 @@ static const struct exynos_soc_id {
{ "EXYNOS7420", 0xE7420000 },
};
static const char * __init product_id_to_soc_id(unsigned int product_id)
static const char *product_id_to_soc_id(unsigned int product_id)
{
int i;
......@@ -46,25 +54,17 @@ static const char * __init product_id_to_soc_id(unsigned int product_id)
return NULL;
}
static int __init exynos_chipid_early_init(void)
static int exynos_chipid_probe(struct platform_device *pdev)
{
struct soc_device_attribute *soc_dev_attr;
struct soc_device *soc_dev;
struct device_node *root;
struct device_node *syscon;
struct regmap *regmap;
u32 product_id;
u32 revision;
int ret;
syscon = of_find_compatible_node(NULL, NULL,
"samsung,exynos4210-chipid");
if (!syscon)
return -ENODEV;
regmap = device_node_to_regmap(syscon);
of_node_put(syscon);
regmap = device_node_to_regmap(pdev->dev.of_node);
if (IS_ERR(regmap))
return PTR_ERR(regmap);
......@@ -74,7 +74,8 @@ static int __init exynos_chipid_early_init(void)
revision = product_id & EXYNOS_REV_MASK;
soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
soc_dev_attr = devm_kzalloc(&pdev->dev, sizeof(*soc_dev_attr),
GFP_KERNEL);
if (!soc_dev_attr)
return -ENOMEM;
......@@ -84,20 +85,24 @@ static int __init exynos_chipid_early_init(void)
of_property_read_string(root, "model", &soc_dev_attr->machine);
of_node_put(root);
soc_dev_attr->revision = kasprintf(GFP_KERNEL, "%x", revision);
soc_dev_attr->revision = devm_kasprintf(&pdev->dev, GFP_KERNEL,
"%x", revision);
soc_dev_attr->soc_id = product_id_to_soc_id(product_id);
if (!soc_dev_attr->soc_id) {
pr_err("Unknown SoC\n");
ret = -ENODEV;
goto err;
return -ENODEV;
}
/* please note that the actual registration will be deferred */
soc_dev = soc_device_register(soc_dev_attr);
if (IS_ERR(soc_dev)) {
ret = PTR_ERR(soc_dev);
if (IS_ERR(soc_dev))
return PTR_ERR(soc_dev);
ret = exynos_asv_init(&pdev->dev, regmap);
if (ret)
goto err;
}
platform_set_drvdata(pdev, soc_dev);
dev_info(soc_device_to_device(soc_dev),
"Exynos: CPU[%s] PRO_ID[0x%x] REV[0x%x] Detected\n",
......@@ -106,9 +111,31 @@ static int __init exynos_chipid_early_init(void)
return 0;
err:
kfree(soc_dev_attr->revision);
kfree(soc_dev_attr);
soc_device_unregister(soc_dev);
return ret;
}
arch_initcall(exynos_chipid_early_init);
static int exynos_chipid_remove(struct platform_device *pdev)
{
struct soc_device *soc_dev = platform_get_drvdata(pdev);
soc_device_unregister(soc_dev);
return 0;
}
static const struct of_device_id exynos_chipid_of_device_ids[] = {
{ .compatible = "samsung,exynos4210-chipid" },
{}
};
static struct platform_driver exynos_chipid_driver = {
.driver = {
.name = "exynos-chipid",
.of_match_table = exynos_chipid_of_device_ids,
},
.probe = exynos_chipid_probe,
.remove = exynos_chipid_remove,
};
builtin_platform_driver(exynos_chipid_driver);
......@@ -16,7 +16,7 @@
#include <linux/delay.h>
#include <linux/of_address.h>
#include <linux/of_platform.h>
#include <linux/sched.h>
#include <linux/pm_runtime.h>
struct exynos_pm_domain_config {
/* Value for LOCAL_PWR_CFG and STATUS fields for each domain */
......@@ -73,15 +73,15 @@ static int exynos_pd_power_off(struct generic_pm_domain *domain)
return exynos_pd_power(domain, false);
}
static const struct exynos_pm_domain_config exynos4210_cfg __initconst = {
static const struct exynos_pm_domain_config exynos4210_cfg = {
.local_pwr_cfg = 0x7,
};
static const struct exynos_pm_domain_config exynos5433_cfg __initconst = {
static const struct exynos_pm_domain_config exynos5433_cfg = {
.local_pwr_cfg = 0xf,
};
static const struct of_device_id exynos_pm_domain_of_match[] __initconst = {
static const struct of_device_id exynos_pm_domain_of_match[] = {
{
.compatible = "samsung,exynos4210-pd",
.data = &exynos4210_cfg,
......@@ -92,7 +92,7 @@ static const struct of_device_id exynos_pm_domain_of_match[] __initconst = {
{ },
};
static __init const char *exynos_get_domain_name(struct device_node *node)
static const char *exynos_get_domain_name(struct device_node *node)
{
const char *name;
......@@ -101,60 +101,44 @@ static __init const char *exynos_get_domain_name(struct device_node *node)
return kstrdup_const(name, GFP_KERNEL);
}
static __init int exynos4_pm_init_power_domain(void)
static int exynos_pd_probe(struct platform_device *pdev)
{
struct device_node *np;
const struct of_device_id *match;
for_each_matching_node_and_match(np, exynos_pm_domain_of_match, &match) {
const struct exynos_pm_domain_config *pm_domain_cfg;
struct exynos_pm_domain *pd;
int on;
const struct exynos_pm_domain_config *pm_domain_cfg;
struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;
struct of_phandle_args child, parent;
struct exynos_pm_domain *pd;
int on, ret;
pm_domain_cfg = match->data;
pm_domain_cfg = of_device_get_match_data(dev);
pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL);
if (!pd)
return -ENOMEM;
pd = kzalloc(sizeof(*pd), GFP_KERNEL);
if (!pd) {
of_node_put(np);
return -ENOMEM;
}
pd->pd.name = exynos_get_domain_name(np);
if (!pd->pd.name) {
kfree(pd);
of_node_put(np);
return -ENOMEM;
}
pd->pd.name = exynos_get_domain_name(np);
if (!pd->pd.name)
return -ENOMEM;
pd->base = of_iomap(np, 0);
if (!pd->base) {
pr_warn("%s: failed to map memory\n", __func__);
kfree_const(pd->pd.name);
kfree(pd);
continue;
}
pd->pd.power_off = exynos_pd_power_off;
pd->pd.power_on = exynos_pd_power_on;
pd->local_pwr_cfg = pm_domain_cfg->local_pwr_cfg;
pd->base = of_iomap(np, 0);
if (!pd->base) {
kfree_const(pd->pd.name);
return -ENODEV;
}
on = readl_relaxed(pd->base + 0x4) & pd->local_pwr_cfg;
pd->pd.power_off = exynos_pd_power_off;
pd->pd.power_on = exynos_pd_power_on;
pd->local_pwr_cfg = pm_domain_cfg->local_pwr_cfg;
pm_genpd_init(&pd->pd, NULL, !on);
of_genpd_add_provider_simple(np, &pd->pd);
}
on = readl_relaxed(pd->base + 0x4) & pd->local_pwr_cfg;
/* Assign the child power domains to their parents */
for_each_matching_node(np, exynos_pm_domain_of_match) {
struct of_phandle_args child, parent;
pm_genpd_init(&pd->pd, NULL, !on);
ret = of_genpd_add_provider_simple(np, &pd->pd);
if (ret == 0 && of_parse_phandle_with_args(np, "power-domains",
"#power-domain-cells", 0, &parent) == 0) {
child.np = np;
child.args_count = 0;
if (of_parse_phandle_with_args(np, "power-domains",
"#power-domain-cells", 0,
&parent) != 0)
continue;
if (of_genpd_add_subdomain(&parent, &child))
pr_warn("%pOF failed to add subdomain: %pOF\n",
parent.np, child.np);
......@@ -163,6 +147,21 @@ static __init int exynos4_pm_init_power_domain(void)
parent.np, child.np);
}
return 0;
pm_runtime_enable(dev);
return ret;
}
static struct platform_driver exynos_pd_driver = {
.probe = exynos_pd_probe,
.driver = {
.name = "exynos-pd",
.of_match_table = exynos_pm_domain_of_match,
.suppress_bind_attrs = true,
}
};
static __init int exynos4_pm_init_power_domain(void)
{
return platform_driver_register(&exynos_pd_driver);
}
core_initcall(exynos4_pm_init_power_domain);
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment