Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  * Qualcomm External Bus Interface 2 (EBI2) driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  * an older version of the Qualcomm Parallel Interface Controller (QPIC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  * Copyright (C) 2016 Linaro Ltd.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8)  * Author: Linus Walleij <linus.walleij@linaro.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10)  * See the device tree bindings for this block for more details on the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11)  * hardware.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) #include <linux/clk.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) #include <linux/of_platform.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) #include <linux/bitops.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26)  * CS0, CS1, CS4 and CS5 are two bits wide, CS2 and CS3 are one bit.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) #define EBI2_CS0_ENABLE_MASK BIT(0)|BIT(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) #define EBI2_CS1_ENABLE_MASK BIT(2)|BIT(3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) #define EBI2_CS2_ENABLE_MASK BIT(4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) #define EBI2_CS3_ENABLE_MASK BIT(5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) #define EBI2_CS4_ENABLE_MASK BIT(6)|BIT(7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) #define EBI2_CS5_ENABLE_MASK BIT(8)|BIT(9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) #define EBI2_CSN_MASK GENMASK(9, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) #define EBI2_XMEM_CFG 0x0000 /* Power management etc */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39)  * SLOW CSn CFG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41)  * Bits 31-28: RECOVERY recovery cycles (0 = 1, 1 = 2 etc) this is the time the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42)  *             memory continues to drive the data bus after OE is de-asserted.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43)  *             Inserted when reading one CS and switching to another CS or read
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44)  *             followed by write on the same CS. Valid values 0 thru 15.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45)  * Bits 27-24: WR_HOLD write hold cycles, these are extra cycles inserted after
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46)  *             every write minimum 1. The data out is driven from the time WE is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47)  *             asserted until CS is asserted. With a hold of 1, the CS stays
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48)  *             active for 1 extra cycle etc. Valid values 0 thru 15.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49)  * Bits 23-16: WR_DELTA initial latency for write cycles inserted for the first
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50)  *             write to a page or burst memory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51)  * Bits 15-8:  RD_DELTA initial latency for read cycles inserted for the first
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52)  *             read to a page or burst memory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53)  * Bits 7-4:   WR_WAIT number of wait cycles for every write access, 0=1 cycle
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54)  *             so 1 thru 16 cycles.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55)  * Bits 3-0:   RD_WAIT number of wait cycles for every read access, 0=1 cycle
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56)  *             so 1 thru 16 cycles.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) #define EBI2_XMEM_CS0_SLOW_CFG 0x0008
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) #define EBI2_XMEM_CS1_SLOW_CFG 0x000C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) #define EBI2_XMEM_CS2_SLOW_CFG 0x0010
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) #define EBI2_XMEM_CS3_SLOW_CFG 0x0014
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) #define EBI2_XMEM_CS4_SLOW_CFG 0x0018
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) #define EBI2_XMEM_CS5_SLOW_CFG 0x001C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) #define EBI2_XMEM_RECOVERY_SHIFT	28
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) #define EBI2_XMEM_WR_HOLD_SHIFT		24
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) #define EBI2_XMEM_WR_DELTA_SHIFT	16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) #define EBI2_XMEM_RD_DELTA_SHIFT	8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) #define EBI2_XMEM_WR_WAIT_SHIFT		4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) #define EBI2_XMEM_RD_WAIT_SHIFT		0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73)  * FAST CSn CFG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74)  * Bits 31-28: ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75)  * Bits 27-24: RD_HOLD: the length in cycles of the first segment of a read
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76)  *             transfer. For a single read trandfer this will be the time
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77)  *             from CS assertion to OE assertion.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78)  * Bits 18-24: ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79)  * Bits 17-16: ADV_OE_RECOVERY, the number of cycles elapsed before an OE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80)  *             assertion, with respect to the cycle where ADV is asserted.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81)  *             2 means 2 cycles between ADV and OE. Values 0, 1, 2 or 3.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82)  * Bits 5:     ADDR_HOLD_ENA, The address is held for an extra cycle to meet
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83)  *             hold time requirements with ADV assertion.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85)  * The manual mentions "write precharge cycles" and "precharge cycles".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86)  * We have not been able to figure out which bit fields these correspond to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87)  * in the hardware, or what valid values exist. The current hypothesis is that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88)  * this is something just used on the FAST chip selects. There is also a "byte
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89)  * device enable" flag somewhere for 8bit memories.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) #define EBI2_XMEM_CS0_FAST_CFG 0x0028
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) #define EBI2_XMEM_CS1_FAST_CFG 0x002C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) #define EBI2_XMEM_CS2_FAST_CFG 0x0030
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) #define EBI2_XMEM_CS3_FAST_CFG 0x0034
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) #define EBI2_XMEM_CS4_FAST_CFG 0x0038
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) #define EBI2_XMEM_CS5_FAST_CFG 0x003C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) #define EBI2_XMEM_RD_HOLD_SHIFT		24
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) #define EBI2_XMEM_ADV_OE_RECOVERY_SHIFT	16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) #define EBI2_XMEM_ADDR_HOLD_ENA_SHIFT	5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)  * struct cs_data - struct with info on a chipselect setting
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)  * @enable_mask: mask to enable the chipselect in the EBI2 config
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)  * @slow_cfg0: offset to XMEMC slow CS config
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)  * @fast_cfg1: offset to XMEMC fast CS config
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) struct cs_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 	u32 enable_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 	u16 slow_cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 	u16 fast_cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) static const struct cs_data cs_info[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 		/* CS0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 		.enable_mask = EBI2_CS0_ENABLE_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 		.slow_cfg = EBI2_XMEM_CS0_SLOW_CFG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 		.fast_cfg = EBI2_XMEM_CS0_FAST_CFG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 		/* CS1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 		.enable_mask = EBI2_CS1_ENABLE_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 		.slow_cfg = EBI2_XMEM_CS1_SLOW_CFG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 		.fast_cfg = EBI2_XMEM_CS1_FAST_CFG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 		/* CS2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 		.enable_mask = EBI2_CS2_ENABLE_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 		.slow_cfg = EBI2_XMEM_CS2_SLOW_CFG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 		.fast_cfg = EBI2_XMEM_CS2_FAST_CFG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 		/* CS3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 		.enable_mask = EBI2_CS3_ENABLE_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 		.slow_cfg = EBI2_XMEM_CS3_SLOW_CFG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 		.fast_cfg = EBI2_XMEM_CS3_FAST_CFG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 		/* CS4 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 		.enable_mask = EBI2_CS4_ENABLE_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 		.slow_cfg = EBI2_XMEM_CS4_SLOW_CFG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 		.fast_cfg = EBI2_XMEM_CS4_FAST_CFG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 		/* CS5 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 		.enable_mask = EBI2_CS5_ENABLE_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 		.slow_cfg = EBI2_XMEM_CS5_SLOW_CFG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 		.fast_cfg = EBI2_XMEM_CS5_FAST_CFG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)  * struct ebi2_xmem_prop - describes an XMEM config property
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)  * @prop: the device tree binding name
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)  * @max: maximum value for the property
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)  * @slowreg: true if this property is in the SLOW CS config register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)  * else it is assumed to be in the FAST config register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)  * @shift: the bit field start in the SLOW or FAST register for this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)  * property
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) struct ebi2_xmem_prop {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 	const char *prop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 	u32 max;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 	bool slowreg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 	u16 shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) static const struct ebi2_xmem_prop xmem_props[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 		.prop = "qcom,xmem-recovery-cycles",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 		.max = 15,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 		.slowreg = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 		.shift = EBI2_XMEM_RECOVERY_SHIFT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 		.prop = "qcom,xmem-write-hold-cycles",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 		.max = 15,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 		.slowreg = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 		.shift = EBI2_XMEM_WR_HOLD_SHIFT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 		.prop = "qcom,xmem-write-delta-cycles",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 		.max = 255,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 		.slowreg = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 		.shift = EBI2_XMEM_WR_DELTA_SHIFT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 		.prop = "qcom,xmem-read-delta-cycles",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 		.max = 255,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 		.slowreg = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 		.shift = EBI2_XMEM_RD_DELTA_SHIFT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 		.prop = "qcom,xmem-write-wait-cycles",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 		.max = 15,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 		.slowreg = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 		.shift = EBI2_XMEM_WR_WAIT_SHIFT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 		.prop = "qcom,xmem-read-wait-cycles",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 		.max = 15,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 		.slowreg = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 		.shift = EBI2_XMEM_RD_WAIT_SHIFT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 		.prop = "qcom,xmem-address-hold-enable",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 		.max = 1, /* boolean prop */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 		.slowreg = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 		.shift = EBI2_XMEM_ADDR_HOLD_ENA_SHIFT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 		.prop = "qcom,xmem-adv-to-oe-recovery-cycles",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 		.max = 3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 		.slowreg = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 		.shift = EBI2_XMEM_ADV_OE_RECOVERY_SHIFT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 		.prop = "qcom,xmem-read-hold-cycles",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 		.max = 15,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 		.slowreg = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 		.shift = EBI2_XMEM_RD_HOLD_SHIFT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) static void qcom_ebi2_setup_chipselect(struct device_node *np,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 				       struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 				       void __iomem *ebi2_base,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 				       void __iomem *ebi2_xmem,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 				       u32 csindex)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 	const struct cs_data *csd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 	u32 slowcfg, fastcfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 	u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 	csd = &cs_info[csindex];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 	val = readl(ebi2_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 	val |= csd->enable_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 	writel(val, ebi2_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 	dev_dbg(dev, "enabled CS%u\n", csindex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 	/* Next set up the XMEMC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 	slowcfg = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 	fastcfg = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 	for (i = 0; i < ARRAY_SIZE(xmem_props); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 		const struct ebi2_xmem_prop *xp = &xmem_props[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 		/* All are regular u32 values */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 		ret = of_property_read_u32(np, xp->prop, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 		if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 			dev_dbg(dev, "could not read %s for CS%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 				xp->prop, csindex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 		/* First check boolean props */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 		if (xp->max == 1 && val) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 			if (xp->slowreg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 				slowcfg |= BIT(xp->shift);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 			else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 				fastcfg |= BIT(xp->shift);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 			dev_dbg(dev, "set %s flag\n", xp->prop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 		/* We're dealing with an u32 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 		if (val > xp->max) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 			dev_err(dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 				"too high value for %s: %u, capped at %u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 				xp->prop, val, xp->max);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 			val = xp->max;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 		if (xp->slowreg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 			slowcfg |= (val << xp->shift);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 			fastcfg |= (val << xp->shift);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 		dev_dbg(dev, "set %s to %u\n", xp->prop, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 	dev_info(dev, "CS%u: SLOW CFG 0x%08x, FAST CFG 0x%08x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 		 csindex, slowcfg, fastcfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 	if (slowcfg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 		writel(slowcfg, ebi2_xmem + csd->slow_cfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 	if (fastcfg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 		writel(fastcfg, ebi2_xmem + csd->fast_cfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) static int qcom_ebi2_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 	struct device_node *np = pdev->dev.of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 	struct device_node *child;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 	struct device *dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 	struct resource *res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 	void __iomem *ebi2_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) 	void __iomem *ebi2_xmem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 	struct clk *ebi2xclk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 	struct clk *ebi2clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 	bool have_children = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 	u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 	ebi2xclk = devm_clk_get(dev, "ebi2x");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 	if (IS_ERR(ebi2xclk))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 		return PTR_ERR(ebi2xclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 	ret = clk_prepare_enable(ebi2xclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 	if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 		dev_err(dev, "could not enable EBI2X clk (%d)\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) 	ebi2clk = devm_clk_get(dev, "ebi2");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 	if (IS_ERR(ebi2clk)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) 		ret = PTR_ERR(ebi2clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) 		goto err_disable_2x_clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) 	ret = clk_prepare_enable(ebi2clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) 	if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) 		dev_err(dev, "could not enable EBI2 clk\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) 		goto err_disable_2x_clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) 	ebi2_base = devm_ioremap_resource(dev, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) 	if (IS_ERR(ebi2_base)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) 		ret = PTR_ERR(ebi2_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) 		goto err_disable_clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) 	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) 	ebi2_xmem = devm_ioremap_resource(dev, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) 	if (IS_ERR(ebi2_xmem)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) 		ret = PTR_ERR(ebi2_xmem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) 		goto err_disable_clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) 	/* Allegedly this turns the power save mode off */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) 	writel(0UL, ebi2_xmem + EBI2_XMEM_CFG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) 	/* Disable all chipselects */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) 	val = readl(ebi2_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) 	val &= ~EBI2_CSN_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) 	writel(val, ebi2_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) 	/* Walk over the child nodes and see what chipselects we use */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) 	for_each_available_child_of_node(np, child) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) 		u32 csindex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) 		/* Figure out the chipselect */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) 		ret = of_property_read_u32(child, "reg", &csindex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) 		if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) 			of_node_put(child);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) 			return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) 		if (csindex > 5) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) 			dev_err(dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) 				"invalid chipselect %u, we only support 0-5\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) 				csindex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) 		qcom_ebi2_setup_chipselect(child,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) 					   dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) 					   ebi2_base,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) 					   ebi2_xmem,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) 					   csindex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) 		/* We have at least one child */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) 		have_children = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) 	if (have_children)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) 		return of_platform_default_populate(np, NULL, dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) err_disable_clk:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) 	clk_disable_unprepare(ebi2clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) err_disable_2x_clk:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) 	clk_disable_unprepare(ebi2xclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) static const struct of_device_id qcom_ebi2_of_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) 	{ .compatible = "qcom,msm8660-ebi2", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) 	{ .compatible = "qcom,apq8060-ebi2", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) 	{ }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) static struct platform_driver qcom_ebi2_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) 	.probe = qcom_ebi2_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) 	.driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) 		.name = "qcom-ebi2",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) 		.of_match_table = qcom_ebi2_of_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) module_platform_driver(qcom_ebi2_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) MODULE_DESCRIPTION("Qualcomm EBI2 driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) MODULE_LICENSE("GPL");