Second set of u-boot-atmel features for 2021.01 cycle

-----BEGIN PGP SIGNATURE-----
 
 iQFQBAABCgA6FiEEqxhEmNJ6d7ZdeFLIHrMeAg6sL8gFAl+NMmQcHGV1Z2VuLmhy
 aXN0ZXZAbWljcm9jaGlwLmNvbQAKCRAesx4CDqwvyLnEB/0cWFfjDfCMY1o7R4QX
 DeDRlD6k6acQWlwa5EiRKwpbPMJKrSI/m5alMCYZG6YHvGtzihqnqohz3gl1sepi
 W7eyyyFsM4hqe4P3lSETJRGWe/O8bNkoa0hBzqZ9btqw2OJLBu4JYB+zKgz8kaDY
 jzkGLgaaK6wtG3rEu+q4fjzp1y9kuz31WnN+9qS8jd/9UH13XKCkJl9TfY5pLfgc
 mmbn2NWtAhi91uShcnIsOpLaNm23IV0ITa22etB9F1docZuUrbhOtiIF45AADjpG
 /xtkV3dEVGml3N/17RizgOwxX3xughG0ak9xifsK6tfgqfVhaGMgkToNNBM+1ddm
 rZZM
 =hF12
 -----END PGP SIGNATURE-----

Merge tag 'u-boot-atmel-2021.01-b' of https://gitlab.denx.de/u-boot/custodians/u-boot-atmel

Second set of u-boot-atmel features for 2021.01 cycle:

This feature set brings the rework of the clock tree for sam9x60 SoC.
This makes the clock tree fully compatible with Common Clock Framework
and allows full clock configuration in U-Boot. This means that the
sam9x60 boards can boot now using U-Boot.
This also includes the definitions for sam9x60 SiPs and a divisor fix
for the clock on sama7g5 SoC.
This commit is contained in:
Tom Rini 2020-10-19 09:29:05 -04:00
commit 7ec87e4192
14 changed files with 729 additions and 206 deletions

View file

@ -12,7 +12,7 @@
#include <dt-bindings/pinctrl/at91.h>
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/clock/at91.h>
#include <dt-bindings/clk/at91.h>
/{
model = "Microchip SAM9X60 SoC";
@ -27,16 +27,26 @@
};
clocks {
slow_rc_osc: slow_rc_osc {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <18500>;
};
main_rc: main_rc {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <12000000>;
};
slow_xtal: slow_xtal {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <0>;
};
main_xtal: main_xtal {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <0>;
};
};
@ -49,8 +59,11 @@
sdhci0: sdhci-host@80000000 {
compatible = "microchip,sam9x60-sdhci";
reg = <0x80000000 0x300>;
clocks = <&sdhci0_clk>, <&sdhci0_gclk>, <&main>;
clock-names = "hclock", "multclk", "baseclk";
clocks = <&pmc PMC_TYPE_PERIPHERAL 12>, <&pmc PMC_TYPE_GCK 12>;
clock-names = "hclock", "multclk";
assigned-clocks = <&pmc PMC_TYPE_GCK 12>;
assigned-clock-rates = <100000000>;
assigned-clock-parents = <&pmc PMC_TYPE_CORE 10>; /* ID_PLL_A_DIV */
bus-width = <4>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_sdhci0>;
@ -66,7 +79,7 @@
compatible = "microchip,sam9x60-qspi";
reg = <0xf0014000 0x100>, <0x70000000 0x10000000>;
reg-names = "qspi_base", "qspi_mmap";
clocks = <&qspi_clk>, <&qspick>;
clocks = <&pmc PMC_TYPE_PERIPHERAL 35>, <&pmc PMC_TYPE_SYSTEM 18>; /* ID_QSPI */
clock-names = "pclk", "qspick";
#address-cells = <1>;
#size-cells = <0>;
@ -76,7 +89,7 @@
flx0: flexcom@f801c600 {
compatible = "atmel,sama5d2-flexcom";
reg = <0xf801c000 0x200>;
clocks = <&flx0_clk>;
clocks = <&pmc PMC_TYPE_PERIPHERAL 5>;
#address-cells = <1>;
#size-cells = <1>;
ranges = <0x0 0xf801c000 0x800>;
@ -89,7 +102,7 @@
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_macb0_rmii>;
clock-names = "hclk", "pclk";
clocks = <&macb0_clk>, <&macb0_clk>;
clocks = <&pmc PMC_TYPE_PERIPHERAL 24>, <&pmc PMC_TYPE_PERIPHERAL 24>;
status = "disabled";
};
@ -98,7 +111,7 @@
reg = <0xfffff200 0x200>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_dbgu>;
clocks = <&dbgu_clk>;
clocks = <&pmc PMC_TYPE_PERIPHERAL 47>;
clock-names = "usart";
};
@ -155,7 +168,7 @@
reg = <0xfffff400 0x200>;
#gpio-cells = <2>;
gpio-controller;
clocks = <&pioA_clk>;
clocks = <&pmc PMC_TYPE_PERIPHERAL 2>;
};
pioB: gpio@fffff600 {
@ -163,7 +176,7 @@
reg = <0xfffff600 0x200>;
#gpio-cells = <2>;
gpio-controller;
clocks = <&pioB_clk>;
clocks = <&pmc PMC_TYPE_PERIPHERAL 3>;
};
pioD: gpio@fffffa00 {
@ -171,143 +184,29 @@
reg = <0xfffffa00 0x200>;
#gpio-cells = <2>;
gpio-controller;
clocks = <&pioD_clk>;
clocks = <&pmc PMC_TYPE_PERIPHERAL 44>;
};
pmc: pmc@fffffc00 {
compatible = "atmel,at91sam9x5-pmc";
compatible = "microchip,sam9x60-pmc";
reg = <0xfffffc00 0x200>;
#address-cells = <1>;
#size-cells = <0>;
main: mainck {
compatible = "atmel,at91sam9x5-clk-main";
#clock-cells = <0>;
};
plla: pllack {
compatible = "microchip,sam9x60-clk-pll";
#clock-cells = <0>;
clocks = <&main>;
reg = <0>;
atmel,clk-input-range = <8000000 24000000>;
#atmel,pll-clk-output-range-cells = <4>;
atmel,pll-clk-output-ranges = <140000000 1200000000 0 0>;
};
mck: masterck {
compatible = "atmel,at91sam9x5-clk-master";
#clock-cells = <0>;
clocks = <&md_slck>, <&main>, <&plla>;
atmel,clk-output-range = <140000000 200000000>;
atmel,clk-divisors = <1 2 4 6>;
};
system: systemck {
compatible = "atmel,at91rm9200-clk-system";
#address-cells = <1>;
#size-cells = <0>;
qspick: qspick {
#clock-cells = <0>;
reg = <19>;
clocks = <&mck>;
};
};
periph: periphck {
compatible = "microchip,sam9x60-clk-peripheral";
#address-cells = <1>;
#size-cells = <0>;
clocks = <&mck>;
pioA_clk: pioA_clk {
#clock-cells = <0>;
reg = <2>;
};
pioB_clk: pioB_clk {
#clock-cells = <0>;
reg = <3>;
};
flx0_clk: flx0_clk {
#clock-cells = <0>;
reg = <5>;
};
pioD_clk: pioD_clk {
#clock-cells = <0>;
reg = <44>;
};
sdhci0_clk: sdhci0_clk {
#clock-cells = <0>;
reg = <12>;
};
dbgu_clk: dbgu_clk {
#clock-cells = <0>;
reg = <47>;
};
macb0_clk: macb0_clk {
#clock-cells = <0>;
reg = <24>;
};
qspi_clk: qspi_clk {
#clock-cells = <0>;
reg = <35>;
};
};
generic: gck {
compatible = "microchip,sam9x60-clk-generated";
#address-cells = <1>;
#size-cells = <0>;
clocks = <&md_slck>, <&td_slck>, <&main>, <&mck>, <&plla>;
sdhci0_gclk: sdhci0_gclk {
#clock-cells = <0>;
reg = <12>;
};
};
#clock-cells = <2>;
clocks = <&clk32 1>, <&clk32 0>, <&main_xtal>, <&main_rc>;
clock-names = "td_slck", "md_slck", "main_xtal", "main_rc";
status = "okay";
};
pit: timer@fffffe40 {
compatible = "atmel,at91sam9260-pit";
reg = <0xfffffe40 0x10>;
clocks = <&mck>;
clocks = <&pmc PMC_TYPE_CORE 11>; /* ID_MCK. */
};
slowckc: sckc@fffffe50 {
compatible = "atmel,at91sam9x5-sckc";
clk32: sckc@fffffe50 {
compatible = "microchip,sam9x60-sckc";
reg = <0xfffffe50 0x4>;
slow_osc: slow_osc {
compatible = "atmel,at91sam9x5-clk-slow-osc";
#clock-cells = <0>;
clocks = <&slow_xtal>;
};
slow_rc_osc: slow_rc_osc {
compatible = "atmel,at91sam9x5-clk-slow-rc-osc";
#clock-cells = <0>;
clock-frequency = <32768>;
};
td_slck: td_slck {
compatible = "atmel,at91sam9x5-clk-slow";
#clock-cells = <0>;
clocks = <&slow_rc_osc>, <&slow_osc>;
};
md_slck: md_slck {
compatible = "atmel,at91sam9x5-clk-slow";
#clock-cells = <0>;
clocks = <&slow_rc_osc>;
};
clocks = <&slow_rc_osc>, <&slow_xtal>;
#clock-cells = <1>;
};
};
};

View file

@ -23,7 +23,7 @@
};
};
&sdhci0 {
&clk32 {
u-boot,dm-pre-reloc;
};
@ -31,7 +31,11 @@
u-boot,dm-pre-reloc;
};
&qspi {
&main_rc {
u-boot,dm-pre-reloc;
};
&main_xtal {
u-boot,dm-pre-reloc;
};
@ -59,74 +63,18 @@
u-boot,dm-pre-reloc;
};
&main {
&qspi {
u-boot,dm-pre-reloc;
};
&plla {
&sdhci0 {
u-boot,dm-pre-reloc;
};
&mck {
u-boot,dm-pre-reloc;
};
&system {
u-boot,dm-pre-reloc;
};
&qspick {
u-boot,dm-pre-reloc;
};
&periph {
u-boot,dm-pre-reloc;
};
&pioA_clk {
u-boot,dm-pre-reloc;
};
&pioB_clk {
u-boot,dm-pre-reloc;
};
&sdhci0_clk {
u-boot,dm-pre-reloc;
};
&dbgu_clk {
u-boot,dm-pre-reloc;
};
&qspi_clk {
u-boot,dm-pre-reloc;
};
&generic {
u-boot,dm-pre-reloc;
};
&sdhci0_gclk {
u-boot,dm-pre-reloc;
};
&slowckc {
u-boot,dm-pre-reloc;
};
&slow_osc {
&slow_xtal {
u-boot,dm-pre-reloc;
};
&slow_rc_osc {
u-boot,dm-pre-reloc;
};
&td_slck {
u-boot,dm-pre-reloc;
};
&md_slck {
u-boot,dm-pre-reloc;
};

View file

@ -18,6 +18,16 @@
i2c0 = &flx0;
};
clocks {
slow_xtal: slow_xtal {
clock-frequency = <32768>;
};
main_xtal: main_xtal {
clock-frequency = <24000000>;
};
};
onewire_tm: onewire {
gpios = <&pioD 14 0>;
pinctrl-names = "default";
@ -57,7 +67,7 @@
pinctrl-0 = <&pinctrl_flx0>;
#address-cells = <1>;
#size-cells = <0>;
clocks = <&flx0_clk>;
clocks = <&pmc PMC_TYPE_PERIPHERAL 5>;
status = "okay";
eeprom@53 {

View file

@ -44,6 +44,12 @@ char *get_cpu_name(void)
switch (extension_id) {
case ARCH_EXID_SAM9X60:
return "SAM9X60";
case ARCH_EXID_SAM9X60_D6K:
return "SAM9X60 8MiB SDRAM SiP";
case ARCH_EXID_SAM9X60_D5M:
return "SAM9X60 64MiB DDR2 SiP";
case ARCH_EXID_SAM9X60_D1G:
return "SAM9X60 128MiB DDR2 SiP";
default:
return "Unknown CPU type";
}

View file

@ -128,6 +128,9 @@
#define ARCH_ID_SAM9X60 0x819b35a0
#define ARCH_ID_VERSION_MASK 0x1f
#define ARCH_EXID_SAM9X60 0x00000000
#define ARCH_EXID_SAM9X60_D6K 0x00000011
#define ARCH_EXID_SAM9X60_D5M 0x00000001
#define ARCH_EXID_SAM9X60_D1G 0x00000010
#define cpu_is_sam9x60() (get_chip_id() == ARCH_ID_SAM9X60)

View file

@ -2,7 +2,7 @@ CONFIG_ARM=y
CONFIG_ARCH_AT91=y
CONFIG_SYS_TEXT_BASE=0x23f00000
CONFIG_TARGET_SAM9X60EK=y
CONFIG_SYS_MALLOC_F_LEN=0x2000
CONFIG_SYS_MALLOC_F_LEN=0x8000
CONFIG_NR_DRAM_BANKS=8
CONFIG_ENV_SIZE=0x4000
CONFIG_DM_GPIO=y
@ -36,8 +36,10 @@ CONFIG_ENV_FAT_DEVICE_AND_PART="0:1"
CONFIG_SYS_RELOC_GD_ENV_ADDR=y
CONFIG_DM=y
CONFIG_CLK=y
CONFIG_CLK_CCF=y
CONFIG_CLK_AT91=y
CONFIG_AT91_GENERIC_CLK=y
CONFIG_AT91_SAM9X60_PLL=y
CONFIG_AT91_GPIO=y
CONFIG_DM_I2C=y
CONFIG_SYS_I2C_AT91=y

View file

@ -2,7 +2,7 @@ CONFIG_ARM=y
CONFIG_ARCH_AT91=y
CONFIG_SYS_TEXT_BASE=0x23f00000
CONFIG_TARGET_SAM9X60EK=y
CONFIG_SYS_MALLOC_F_LEN=0x2000
CONFIG_SYS_MALLOC_F_LEN=0x8000
CONFIG_NR_DRAM_BANKS=8
CONFIG_DM_GPIO=y
CONFIG_DEBUG_UART_BOARD_INIT=y
@ -40,8 +40,10 @@ CONFIG_SYS_REDUNDAND_ENVIRONMENT=y
CONFIG_SYS_RELOC_GD_ENV_ADDR=y
CONFIG_DM=y
CONFIG_CLK=y
CONFIG_CLK_CCF=y
CONFIG_CLK_AT91=y
CONFIG_AT91_GENERIC_CLK=y
CONFIG_AT91_SAM9X60_PLL=y
CONFIG_AT91_GPIO=y
CONFIG_DM_I2C=y
CONFIG_SYS_I2C_AT91=y

View file

@ -2,7 +2,7 @@ CONFIG_ARM=y
CONFIG_ARCH_AT91=y
CONFIG_SYS_TEXT_BASE=0x23f00000
CONFIG_TARGET_SAM9X60EK=y
CONFIG_SYS_MALLOC_F_LEN=0x2000
CONFIG_SYS_MALLOC_F_LEN=0x8000
CONFIG_NR_DRAM_BANKS=8
CONFIG_ENV_SECT_SIZE=0x1000
CONFIG_DM_GPIO=y
@ -48,8 +48,10 @@ CONFIG_ENV_SPI_MODE=0x0
CONFIG_SYS_RELOC_GD_ENV_ADDR=y
CONFIG_DM=y
CONFIG_CLK=y
CONFIG_CLK_CCF=y
CONFIG_CLK_AT91=y
CONFIG_AT91_GENERIC_CLK=y
CONFIG_AT91_SAM9X60_PLL=y
CONFIG_AT91_GPIO=y
CONFIG_DM_I2C=y
CONFIG_SYS_I2C_AT91=y

View file

@ -10,6 +10,7 @@ obj-$(CONFIG_AT91_GENERIC_CLK) += clk-generic.o
obj-$(CONFIG_AT91_UTMI) += clk-utmi.o
obj-$(CONFIG_AT91_SAM9X60_PLL) += clk-sam9x60-pll.o
obj-$(CONFIG_SAMA7G5) += sama7g5.o
obj-$(CONFIG_SAM9X60) += sam9x60.o
else
obj-y += compat.o
endif

View file

@ -24,7 +24,7 @@
#define MASTER_PRES_MASK 0x7
#define MASTER_PRES_MAX MASTER_PRES_MASK
#define MASTER_DIV_SHIFT 8
#define MASTER_DIV_MASK 0x3
#define MASTER_DIV_MASK 0x7
#define PMC_MCR 0x30
#define PMC_MCR_ID_MSK GENMASK(3, 0)

View file

@ -30,7 +30,7 @@ extern const struct clk_master_layout at91sam9x5_master_layout;
struct clk_master_characteristics {
struct clk_range output;
u32 divisors[4];
u32 divisors[5];
u8 have_div3_pres;
};

649
drivers/clk/at91/sam9x60.c Normal file
View file

@ -0,0 +1,649 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2020 Microchip Technology Inc. and its subsidiaries
*
* Author: Claudiu Beznea <claudiu.beznea@microchip.com>
*
* Based on sam9x60.c on Linux.
*/
#include <common.h>
#include <clk-uclass.h>
#include <dm.h>
#include <dt-bindings/clk/at91.h>
#include <linux/clk-provider.h>
#include "pmc.h"
/**
* Clock identifiers to be used in conjunction with macros like
* AT91_TO_CLK_ID()
*
* @ID_MD_SLCK: TD slow clock identifier
* @ID_TD_SLCK: MD slow clock identifier
* @ID_MAIN_XTAL: Main Xtal clock identifier
* @ID_MAIN_RC: Main RC clock identifier
* @ID_MAIN_RC_OSC: Main RC Oscillator clock identifier
* @ID_MAIN_OSC: Main Oscillator clock identifier
* @ID_MAINCK: MAINCK clock identifier
* @ID_PLL_U_FRAC: UPLL fractional clock identifier
* @ID_PLL_U_DIV: UPLL divider clock identifier
* @ID_PLL_A_FRAC: APLL fractional clock identifier
* @ID_PLL_A_DIV: APLL divider clock identifier
* @ID_MCK: MCK clock identifier
* @ID_UTMI: UTMI clock identifier
* @ID_PROG0: Programmable 0 clock identifier
* @ID_PROG1: Programmable 1 clock identifier
* @ID_PCK0: PCK0 system clock identifier
* @ID_PCK1: PCK1 system clock identifier
* @ID_DDR: DDR system clock identifier
* @ID_QSPI: QSPI system clock identifier
*
* Note: if changing the values of this enums please sync them with
* device tree
*/
enum pmc_clk_ids {
ID_MD_SLCK = 0,
ID_TD_SLCK = 1,
ID_MAIN_XTAL = 2,
ID_MAIN_RC = 3,
ID_MAIN_RC_OSC = 4,
ID_MAIN_OSC = 5,
ID_MAINCK = 6,
ID_PLL_U_FRAC = 7,
ID_PLL_U_DIV = 8,
ID_PLL_A_FRAC = 9,
ID_PLL_A_DIV = 10,
ID_MCK = 11,
ID_UTMI = 12,
ID_PROG0 = 13,
ID_PROG1 = 14,
ID_PCK0 = 15,
ID_PCK1 = 16,
ID_DDR = 17,
ID_QSPI = 18,
ID_MAX,
};
/**
* PLL type identifiers
* @PLL_TYPE_FRAC: fractional PLL identifier
* @PLL_TYPE_DIV: divider PLL identifier
*/
enum pll_type {
PLL_TYPE_FRAC,
PLL_TYPE_DIV,
};
/* Clock names used as parents for multiple clocks. */
static const char *clk_names[] = {
[ID_MAIN_RC_OSC] = "main_rc_osc",
[ID_MAIN_OSC] = "main_osc",
[ID_MAINCK] = "mainck",
[ID_PLL_U_DIV] = "upll_divpmcck",
[ID_PLL_A_DIV] = "plla_divpmcck",
[ID_MCK] = "mck",
};
/* Fractional PLL output range. */
static const struct clk_range plla_outputs[] = {
{ .min = 2343750, .max = 1200000000 },
};
static const struct clk_range upll_outputs[] = {
{ .min = 300000000, .max = 500000000 },
};
/* PLL characteristics. */
static const struct clk_pll_characteristics apll_characteristics = {
.input = { .min = 12000000, .max = 48000000 },
.num_output = ARRAY_SIZE(plla_outputs),
.output = plla_outputs,
};
static const struct clk_pll_characteristics upll_characteristics = {
.input = { .min = 12000000, .max = 48000000 },
.num_output = ARRAY_SIZE(upll_outputs),
.output = upll_outputs,
.upll = true,
};
/* Layout for fractional PLLs. */
static const struct clk_pll_layout pll_layout_frac = {
.mul_mask = GENMASK(31, 24),
.frac_mask = GENMASK(21, 0),
.mul_shift = 24,
.frac_shift = 0,
};
/* Layout for DIV PLLs. */
static const struct clk_pll_layout pll_layout_div = {
.div_mask = GENMASK(7, 0),
.endiv_mask = BIT(29),
.div_shift = 0,
.endiv_shift = 29,
};
/* MCK characteristics. */
static const struct clk_master_characteristics mck_characteristics = {
.output = { .min = 140000000, .max = 200000000 },
.divisors = { 1, 2, 4, 3 },
.have_div3_pres = 1,
};
/* MCK layout. */
static const struct clk_master_layout mck_layout = {
.mask = 0x373,
.pres_shift = 4,
.offset = 0x28,
};
/* Programmable clock layout. */
static const struct clk_programmable_layout programmable_layout = {
.pres_mask = 0xff,
.pres_shift = 8,
.css_mask = 0x1f,
.have_slck_mck = 0,
.is_pres_direct = 1,
};
/* Peripheral clock layout. */
static const struct clk_pcr_layout pcr_layout = {
.offset = 0x88,
.cmd = BIT(31),
.gckcss_mask = GENMASK(12, 8),
.pid_mask = GENMASK(6, 0),
};
/**
* PLL clocks description
* @n: clock name
* @p: clock parent
* @l: clock layout
* @t: clock type
* @f: true if clock is fixed and not changeable by driver
* @id: clock id corresponding to PLL driver
* @cid: clock id corresponding to clock subsystem
*/
static const struct {
const char *n;
const char *p;
const struct clk_pll_layout *l;
const struct clk_pll_characteristics *c;
u8 t;
u8 f;
u8 id;
u8 cid;
} sam9x60_plls[] = {
{
.n = "plla_fracck",
.p = "mainck",
.l = &pll_layout_frac,
.c = &apll_characteristics,
.t = PLL_TYPE_FRAC,
.f = 1,
.id = 0,
.cid = ID_PLL_A_FRAC,
},
{
.n = "plla_divpmcck",
.p = "plla_fracck",
.l = &pll_layout_div,
.c = &apll_characteristics,
.t = PLL_TYPE_DIV,
.f = 1,
.id = 0,
.cid = ID_PLL_A_DIV,
},
{
.n = "upll_fracck",
.p = "main_osc",
.l = &pll_layout_frac,
.c = &upll_characteristics,
.t = PLL_TYPE_FRAC,
.f = 1,
.id = 1,
.cid = ID_PLL_U_FRAC,
},
{
.n = "upll_divpmcck",
.p = "upll_fracck",
.l = &pll_layout_div,
.c = &upll_characteristics,
.t = PLL_TYPE_DIV,
.f = 1,
.id = 1,
.cid = ID_PLL_U_DIV,
},
};
/**
* Programmable clock description
* @n: clock name
* @cid: clock id corresponding to clock subsystem
*/
static const struct {
const char *n;
u8 cid;
} sam9x60_prog[] = {
{ .n = "prog0", .cid = ID_PROG0, },
{ .n = "prog1", .cid = ID_PROG1, },
};
/* Mux table for programmable clocks. */
static u32 sam9x60_prog_mux_table[] = { 0, 1, 2, 3, 4, 5, };
/**
* System clock description
* @n: clock name
* @p: parent clock name
* @id: clock id corresponding to system clock driver
* @cid: clock id corresponding to clock subsystem
*/
static const struct {
const char *n;
const char *p;
u8 id;
u8 cid;
} sam9x60_systemck[] = {
{ .n = "ddrck", .p = "mck", .id = 2, .cid = ID_DDR, },
{ .n = "pck0", .p = "prog0", .id = 8, .cid = ID_PCK0, },
{ .n = "pck1", .p = "prog1", .id = 9, .cid = ID_PCK1, },
{ .n = "qspick", .p = "mck", .id = 19, .cid = ID_QSPI, },
};
/**
* Peripheral clock description
* @n: clock name
* @id: clock id
*/
static const struct {
const char *n;
u8 id;
} sam9x60_periphck[] = {
{ .n = "pioA_clk", .id = 2, },
{ .n = "pioB_clk", .id = 3, },
{ .n = "pioC_clk", .id = 4, },
{ .n = "flex0_clk", .id = 5, },
{ .n = "flex1_clk", .id = 6, },
{ .n = "flex2_clk", .id = 7, },
{ .n = "flex3_clk", .id = 8, },
{ .n = "flex6_clk", .id = 9, },
{ .n = "flex7_clk", .id = 10, },
{ .n = "flex8_clk", .id = 11, },
{ .n = "sdmmc0_clk", .id = 12, },
{ .n = "flex4_clk", .id = 13, },
{ .n = "flex5_clk", .id = 14, },
{ .n = "flex9_clk", .id = 15, },
{ .n = "flex10_clk", .id = 16, },
{ .n = "tcb0_clk", .id = 17, },
{ .n = "pwm_clk", .id = 18, },
{ .n = "adc_clk", .id = 19, },
{ .n = "dma0_clk", .id = 20, },
{ .n = "matrix_clk", .id = 21, },
{ .n = "uhphs_clk", .id = 22, },
{ .n = "udphs_clk", .id = 23, },
{ .n = "macb0_clk", .id = 24, },
{ .n = "lcd_clk", .id = 25, },
{ .n = "sdmmc1_clk", .id = 26, },
{ .n = "macb1_clk", .id = 27, },
{ .n = "ssc_clk", .id = 28, },
{ .n = "can0_clk", .id = 29, },
{ .n = "can1_clk", .id = 30, },
{ .n = "flex11_clk", .id = 32, },
{ .n = "flex12_clk", .id = 33, },
{ .n = "i2s_clk", .id = 34, },
{ .n = "qspi_clk", .id = 35, },
{ .n = "gfx2d_clk", .id = 36, },
{ .n = "pit64b_clk", .id = 37, },
{ .n = "trng_clk", .id = 38, },
{ .n = "aes_clk", .id = 39, },
{ .n = "tdes_clk", .id = 40, },
{ .n = "sha_clk", .id = 41, },
{ .n = "classd_clk", .id = 42, },
{ .n = "isi_clk", .id = 43, },
{ .n = "pioD_clk", .id = 44, },
{ .n = "tcb1_clk", .id = 45, },
{ .n = "dbgu_clk", .id = 47, },
{ .n = "mpddr_clk", .id = 49, },
};
/**
* Generic clock description
* @n: clock name
* @ep: extra parents parents names
* @ep_mux_table: extra parents mux table
* @ep_clk_mux_table: extra parents clock mux table (for CCF)
* @r: clock output range
* @ep_count: extra parents count
* @id: clock id
*/
static const struct {
const char *n;
struct clk_range r;
u8 id;
} sam9x60_gck[] = {
{ .n = "flex0_gclk", .id = 5, },
{ .n = "flex1_gclk", .id = 6, },
{ .n = "flex2_gclk", .id = 7, },
{ .n = "flex3_gclk", .id = 8, },
{ .n = "flex6_gclk", .id = 9, },
{ .n = "flex7_gclk", .id = 10, },
{ .n = "flex8_gclk", .id = 11, },
{ .n = "sdmmc0_gclk", .id = 12, .r = { .min = 0, .max = 105000000 }, },
{ .n = "flex4_gclk", .id = 13, },
{ .n = "flex5_gclk", .id = 14, },
{ .n = "flex9_gclk", .id = 15, },
{ .n = "flex10_gclk", .id = 16, },
{ .n = "tcb0_gclk", .id = 17, },
{ .n = "adc_gclk", .id = 19, },
{ .n = "lcd_gclk", .id = 25, .r = { .min = 0, .max = 140000000 }, },
{ .n = "sdmmc1_gclk", .id = 26, .r = { .min = 0, .max = 105000000 }, },
{ .n = "flex11_gclk", .id = 32, },
{ .n = "flex12_gclk", .id = 33, },
{ .n = "i2s_gclk", .id = 34, .r = { .min = 0, .max = 105000000 }, },
{ .n = "pit64b_gclk", .id = 37, },
{ .n = "classd_gclk", .id = 42, .r = { .min = 0, .max = 100000000 }, },
{ .n = "tcb1_gclk", .id = 45, },
{ .n = "dbgu_gclk", .id = 47, },
};
#define prepare_mux_table(_allocs, _index, _dst, _src, _num, _label) \
do { \
int _i; \
(_dst) = kzalloc(sizeof(*(_dst)) * (_num), GFP_KERNEL); \
if (!(_dst)) { \
ret = -ENOMEM; \
goto _label; \
} \
(_allocs)[(_index)++] = (_dst); \
for (_i = 0; _i < (_num); _i++) \
(_dst)[_i] = (_src)[_i]; \
} while (0)
static int sam9x60_clk_probe(struct udevice *dev)
{
void __iomem *base = (void *)devfdt_get_addr_ptr(dev);
unsigned int *clkmuxallocs[64], *muxallocs[64];
const char *p[10];
unsigned int cm[10], m[10], *tmpclkmux, *tmpmux;
struct clk clk, *c;
bool main_osc_bypass;
int ret, muxallocindex = 0, clkmuxallocindex = 0, i;
static const struct clk_range r = { 0, 0 };
if (!base)
return -EINVAL;
memset(muxallocs, 0, ARRAY_SIZE(muxallocs));
memset(clkmuxallocs, 0, ARRAY_SIZE(clkmuxallocs));
ret = clk_get_by_index(dev, 0, &clk);
if (ret)
return ret;
ret = clk_get_by_id(clk.id, &c);
if (ret)
return ret;
clk_names[ID_TD_SLCK] = kmemdup(clk_hw_get_name(c),
strlen(clk_hw_get_name(c)) + 1,
GFP_KERNEL);
if (!clk_names[ID_TD_SLCK])
return -ENOMEM;
ret = clk_get_by_index(dev, 1, &clk);
if (ret)
return ret;
ret = clk_get_by_id(clk.id, &c);
if (ret)
return ret;
clk_names[ID_MD_SLCK] = kmemdup(clk_hw_get_name(c),
strlen(clk_hw_get_name(c)) + 1,
GFP_KERNEL);
if (!clk_names[ID_MD_SLCK])
return -ENOMEM;
ret = clk_get_by_index(dev, 2, &clk);
if (ret)
return ret;
clk_names[ID_MAIN_XTAL] = kmemdup(clk_hw_get_name(&clk),
strlen(clk_hw_get_name(&clk)) + 1,
GFP_KERNEL);
if (!clk_names[ID_MAIN_XTAL])
return -ENOMEM;
ret = clk_get_by_index(dev, 3, &clk);
if (ret)
goto fail;
clk_names[ID_MAIN_RC] = kmemdup(clk_hw_get_name(&clk),
strlen(clk_hw_get_name(&clk)) + 1,
GFP_KERNEL);
if (ret)
goto fail;
main_osc_bypass = dev_read_bool(dev, "atmel,main-osc-bypass");
/* Register main rc oscillator. */
c = at91_clk_main_rc(base, clk_names[ID_MAIN_RC_OSC],
clk_names[ID_MAIN_RC]);
if (IS_ERR(c)) {
ret = PTR_ERR(c);
goto fail;
}
clk_dm(AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_MAIN_RC_OSC), c);
/* Register main oscillator. */
c = at91_clk_main_osc(base, clk_names[ID_MAIN_OSC],
clk_names[ID_MAIN_XTAL], main_osc_bypass);
if (IS_ERR(c)) {
ret = PTR_ERR(c);
goto fail;
}
clk_dm(AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_MAIN_OSC), c);
/* Register mainck. */
p[0] = clk_names[ID_MAIN_RC_OSC];
p[1] = clk_names[ID_MAIN_OSC];
cm[0] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_MAIN_RC_OSC);
cm[1] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_MAIN_OSC);
prepare_mux_table(clkmuxallocs, clkmuxallocindex, tmpclkmux, cm, 2,
fail);
c = at91_clk_sam9x5_main(base, clk_names[ID_MAINCK], p,
2, tmpclkmux, PMC_TYPE_CORE);
if (IS_ERR(c)) {
ret = PTR_ERR(c);
goto fail;
}
clk_dm(AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_MAINCK), c);
/* Register PLL fracs clocks. */
for (i = 0; i < ARRAY_SIZE(sam9x60_plls); i++) {
if (sam9x60_plls[i].t != PLL_TYPE_FRAC)
continue;
c = sam9x60_clk_register_frac_pll(base, sam9x60_plls[i].n,
sam9x60_plls[i].p,
sam9x60_plls[i].id,
sam9x60_plls[i].c,
sam9x60_plls[i].l,
sam9x60_plls[i].f);
if (IS_ERR(c)) {
ret = PTR_ERR(c);
goto fail;
}
clk_dm(AT91_TO_CLK_ID(PMC_TYPE_CORE, sam9x60_plls[i].cid), c);
}
/* Register PLL div clocks. */
for (i = 0; i < ARRAY_SIZE(sam9x60_plls); i++) {
if (sam9x60_plls[i].t != PLL_TYPE_DIV)
continue;
c = sam9x60_clk_register_div_pll(base, sam9x60_plls[i].n,
sam9x60_plls[i].p,
sam9x60_plls[i].id,
sam9x60_plls[i].c,
sam9x60_plls[i].l,
sam9x60_plls[i].f);
if (IS_ERR(c)) {
ret = PTR_ERR(c);
goto fail;
}
clk_dm(AT91_TO_CLK_ID(PMC_TYPE_CORE, sam9x60_plls[i].cid), c);
}
/* Register MCK clock. */
p[0] = clk_names[ID_MD_SLCK];
p[1] = clk_names[ID_MAINCK];
p[2] = clk_names[ID_PLL_A_DIV];
p[3] = clk_names[ID_PLL_U_DIV];
cm[0] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_MD_SLCK);
cm[1] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_MAINCK);
cm[2] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_PLL_A_DIV);
cm[3] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_PLL_U_DIV);
prepare_mux_table(clkmuxallocs, clkmuxallocindex, tmpclkmux, cm, 4,
fail);
c = at91_clk_register_master(base, clk_names[ID_MCK], p, 4, &mck_layout,
&mck_characteristics, tmpclkmux);
if (IS_ERR(c)) {
ret = PTR_ERR(c);
goto fail;
}
clk_dm(AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_MCK), c);
/* Register programmable clocks. */
p[0] = clk_names[ID_MD_SLCK];
p[1] = clk_names[ID_TD_SLCK];
p[2] = clk_names[ID_MAINCK];
p[3] = clk_names[ID_MCK];
p[4] = clk_names[ID_PLL_A_DIV];
p[5] = clk_names[ID_PLL_U_DIV];
cm[0] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_MD_SLCK);
cm[1] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_TD_SLCK);
cm[2] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_MAINCK);
cm[3] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_MCK);
cm[4] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_PLL_A_DIV);
cm[5] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_PLL_U_DIV);
for (i = 0; i < ARRAY_SIZE(sam9x60_prog); i++) {
prepare_mux_table(clkmuxallocs, clkmuxallocindex, tmpclkmux, cm,
6, fail);
c = at91_clk_register_programmable(base, sam9x60_prog[i].n, p,
10, i, &programmable_layout,
tmpclkmux,
sam9x60_prog_mux_table);
if (IS_ERR(c)) {
ret = PTR_ERR(c);
goto fail;
}
clk_dm(AT91_TO_CLK_ID(PMC_TYPE_CORE, sam9x60_prog[i].cid), c);
}
/* System clocks. */
for (i = 0; i < ARRAY_SIZE(sam9x60_systemck); i++) {
c = at91_clk_register_system(base, sam9x60_systemck[i].n,
sam9x60_systemck[i].p,
sam9x60_systemck[i].id);
if (IS_ERR(c)) {
ret = PTR_ERR(c);
goto fail;
}
clk_dm(AT91_TO_CLK_ID(PMC_TYPE_SYSTEM, sam9x60_systemck[i].cid),
c);
}
/* Peripheral clocks. */
for (i = 0; i < ARRAY_SIZE(sam9x60_periphck); i++) {
c = at91_clk_register_sam9x5_peripheral(base, &pcr_layout,
sam9x60_periphck[i].n,
clk_names[ID_MCK],
sam9x60_periphck[i].id,
&r);
if (IS_ERR(c)) {
ret = PTR_ERR(c);
goto fail;
}
clk_dm(AT91_TO_CLK_ID(PMC_TYPE_PERIPHERAL,
sam9x60_periphck[i].id), c);
}
/* Generic clocks. */
p[0] = clk_names[ID_MD_SLCK];
p[1] = clk_names[ID_TD_SLCK];
p[2] = clk_names[ID_MAINCK];
p[3] = clk_names[ID_MCK];
p[4] = clk_names[ID_PLL_A_DIV];
p[5] = clk_names[ID_PLL_U_DIV];
m[0] = 0;
m[1] = 1;
m[2] = 2;
m[3] = 3;
m[4] = 4;
m[5] = 5;
cm[0] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_MD_SLCK);
cm[1] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_TD_SLCK);
cm[2] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_MAINCK);
cm[3] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_MCK);
cm[4] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_PLL_A_DIV);
cm[5] = AT91_TO_CLK_ID(PMC_TYPE_CORE, ID_PLL_U_DIV);
for (i = 0; i < ARRAY_SIZE(sam9x60_gck); i++) {
prepare_mux_table(clkmuxallocs, clkmuxallocindex, tmpclkmux, cm,
6, fail);
prepare_mux_table(muxallocs, muxallocindex, tmpmux, m,
6, fail);
c = at91_clk_register_generic(base, &pcr_layout,
sam9x60_gck[i].n, p, tmpclkmux,
tmpmux, 6, sam9x60_gck[i].id,
&sam9x60_gck[i].r);
if (IS_ERR(c)) {
ret = PTR_ERR(c);
goto fail;
}
clk_dm(AT91_TO_CLK_ID(PMC_TYPE_GCK, sam9x60_gck[i].id), c);
}
return 0;
fail:
for (i = 0; i < ARRAY_SIZE(muxallocs); i++)
kfree(muxallocs[i]);
for (i = 0; i < ARRAY_SIZE(clkmuxallocs); i++)
kfree(clkmuxallocs[i]);
return ret;
}
static const struct udevice_id sam9x60_clk_ids[] = {
{ .compatible = "microchip,sam9x60-pmc" },
{ /* Sentinel. */ },
};
U_BOOT_DRIVER(at91_sam9x60_pmc) = {
.name = "at91-sam9x60-pmc",
.id = UCLASS_CLK,
.of_match = sam9x60_clk_ids,
.ops = &at91_clk_ops,
.probe = sam9x60_clk_probe,
.flags = DM_FLAG_PRE_RELOC,
};

View file

@ -189,13 +189,13 @@ static const struct clk_pll_layout pll_layout_divio = {
/* MCK0 characteristics. */
static const struct clk_master_characteristics mck0_characteristics = {
.output = { .min = 140000000, .max = 200000000 },
.divisors = { 1, 2, 4, 3 },
.divisors = { 1, 2, 4, 3, 5 },
.have_div3_pres = 1,
};
/* MCK0 layout. */
static const struct clk_master_layout mck0_layout = {
.mask = 0x373,
.mask = 0x773,
.pres_shift = 4,
.offset = 0x28,
};

View file

@ -40,7 +40,8 @@
#define CONFIG_SYS_SDRAM_SIZE 0x10000000 /* 256 megs */
#define CONFIG_SYS_INIT_SP_ADDR \
(CONFIG_SYS_SDRAM_BASE + 16 * 1024 - GENERATED_GBL_DATA_SIZE)
(CONFIG_SYS_SDRAM_BASE + 16 * 1024 + CONFIG_SYS_MALLOC_F_LEN - \
GENERATED_GBL_DATA_SIZE)
/* NAND flash */
#ifdef CONFIG_CMD_NAND