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