Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

sata, highbank: set tx_atten override bits

Some board designs do not drive the SATA transmit lines within the
specification. The ECME can provide override settings, on a per board
basis, to bring the transmit lines within spec. Read those settings
from the DTB and program them in.

At the time of submission, no production hardware requires this patch.

Signed-off-by: Mark Langsdorf <mark.langsdorf@calxeda.com>
Signed-off-by: Tejun Heo <tj@kernel.org>

authored by

Mark Langsdorf and committed by
Tejun Heo
b2e4c7b9 91c20950

+49 -13
+4
Documentation/devicetree/bindings/ata/sata_highbank.txt
··· 20 20 indicator lights using the indicated GPIOs 21 21 - calxeda,led-order : a u32 array that map port numbers to offsets within the 22 22 SGPIO bitstream. 23 + - calxeda,tx-atten : a u32 array that contains TX attenuation override 24 + codes, one per port. The upper 3 bytes are always 25 + 0 and thus ignored. 23 26 24 27 Example: 25 28 sata@ffe08000 { ··· 34 31 &combophy0 2 &combophy0 3>; 35 32 calxeda,sgpio-gpio =<&gpioh 5 1 &gpioh 6 1 &gpioh 7 1>; 36 33 calxeda,led-order = <4 0 1 2 3>; 34 + calxeda,tx-atten = <0xff 22 0xff 0xff 23>; 37 35 };
+45 -13
drivers/ata/sata_highbank.c
··· 46 46 #define CR_BUSY 0x0001 47 47 #define CR_START 0x0001 48 48 #define CR_WR_RDN 0x0002 49 + #define CPHY_TX_INPUT_STS 0x2001 49 50 #define CPHY_RX_INPUT_STS 0x2002 50 - #define CPHY_SATA_OVERRIDE 0x4000 51 - #define CPHY_OVERRIDE 0x2005 51 + #define CPHY_SATA_TX_OVERRIDE 0x8000 52 + #define CPHY_SATA_RX_OVERRIDE 0x4000 53 + #define CPHY_TX_OVERRIDE 0x2004 54 + #define CPHY_RX_OVERRIDE 0x2005 52 55 #define SPHY_LANE 0x100 53 56 #define SPHY_HALF_RATE 0x0001 54 57 #define CPHY_SATA_DPLL_MODE 0x0700 55 58 #define CPHY_SATA_DPLL_SHIFT 8 56 59 #define CPHY_SATA_DPLL_RESET (1 << 11) 60 + #define CPHY_SATA_TX_ATTEN 0x1c00 61 + #define CPHY_SATA_TX_ATTEN_SHIFT 10 57 62 #define CPHY_PHY_COUNT 6 58 63 #define CPHY_LANE_COUNT 4 59 64 #define CPHY_PORT_COUNT (CPHY_PHY_COUNT * CPHY_LANE_COUNT) ··· 71 66 void __iomem *phy_base; 72 67 u8 lane_mapping; 73 68 u8 phy_devs; 69 + u8 tx_atten; 74 70 }; 75 71 static struct phy_lane_info port_data[CPHY_PORT_COUNT]; 76 72 ··· 82 76 #define SGPIO_PINS 3 83 77 #define SGPIO_PORTS 8 84 78 85 - /* can be cast as an ahci_host_priv for compatibility with most functions */ 86 79 struct ecx_plat_data { 87 80 u32 n_ports; 88 81 unsigned sgpio_gpio[SGPIO_PINS]; ··· 264 259 if (unlikely(port_data[sata_port].phy_base == NULL)) 265 260 return; 266 261 tmp = combo_phy_read(sata_port, CPHY_RX_INPUT_STS + lane * SPHY_LANE); 267 - tmp &= ~CPHY_SATA_OVERRIDE; 268 - combo_phy_write(sata_port, CPHY_OVERRIDE + lane * SPHY_LANE, tmp); 262 + tmp &= ~CPHY_SATA_RX_OVERRIDE; 263 + combo_phy_write(sata_port, CPHY_RX_OVERRIDE + lane * SPHY_LANE, tmp); 264 + } 265 + 266 + static void cphy_override_tx_attenuation(u8 sata_port, u32 val) 267 + { 268 + u8 lane = port_data[sata_port].lane_mapping; 269 + u32 tmp; 270 + 271 + if (val & 0x8) 272 + return; 273 + 274 + tmp = combo_phy_read(sata_port, CPHY_TX_INPUT_STS + lane * SPHY_LANE); 275 + tmp &= ~CPHY_SATA_TX_OVERRIDE; 276 + combo_phy_write(sata_port, CPHY_TX_OVERRIDE + lane * SPHY_LANE, tmp); 277 + 278 + tmp |= CPHY_SATA_TX_OVERRIDE; 279 + combo_phy_write(sata_port, CPHY_TX_OVERRIDE + lane * SPHY_LANE, tmp); 280 + 281 + tmp |= (val << CPHY_SATA_TX_ATTEN_SHIFT) & CPHY_SATA_TX_ATTEN; 282 + combo_phy_write(sata_port, CPHY_TX_OVERRIDE + lane * SPHY_LANE, tmp); 269 283 } 270 284 271 285 static void cphy_override_rx_mode(u8 sata_port, u32 val) ··· 292 268 u8 lane = port_data[sata_port].lane_mapping; 293 269 u32 tmp; 294 270 tmp = combo_phy_read(sata_port, CPHY_RX_INPUT_STS + lane * SPHY_LANE); 295 - tmp &= ~CPHY_SATA_OVERRIDE; 296 - combo_phy_write(sata_port, CPHY_OVERRIDE + lane * SPHY_LANE, tmp); 271 + tmp &= ~CPHY_SATA_RX_OVERRIDE; 272 + combo_phy_write(sata_port, CPHY_RX_OVERRIDE + lane * SPHY_LANE, tmp); 297 273 298 - tmp |= CPHY_SATA_OVERRIDE; 299 - combo_phy_write(sata_port, CPHY_OVERRIDE + lane * SPHY_LANE, tmp); 274 + tmp |= CPHY_SATA_RX_OVERRIDE; 275 + combo_phy_write(sata_port, CPHY_RX_OVERRIDE + lane * SPHY_LANE, tmp); 300 276 301 277 tmp &= ~CPHY_SATA_DPLL_MODE; 302 278 tmp |= val << CPHY_SATA_DPLL_SHIFT; 303 - combo_phy_write(sata_port, CPHY_OVERRIDE + lane * SPHY_LANE, tmp); 279 + combo_phy_write(sata_port, CPHY_RX_OVERRIDE + lane * SPHY_LANE, tmp); 304 280 305 281 tmp |= CPHY_SATA_DPLL_RESET; 306 - combo_phy_write(sata_port, CPHY_OVERRIDE + lane * SPHY_LANE, tmp); 282 + combo_phy_write(sata_port, CPHY_RX_OVERRIDE + lane * SPHY_LANE, tmp); 307 283 308 284 tmp &= ~CPHY_SATA_DPLL_RESET; 309 - combo_phy_write(sata_port, CPHY_OVERRIDE + lane * SPHY_LANE, tmp); 285 + combo_phy_write(sata_port, CPHY_RX_OVERRIDE + lane * SPHY_LANE, tmp); 310 286 311 287 msleep(15); 312 288 } ··· 323 299 lane * SPHY_LANE); 324 300 } while ((tmp & SPHY_HALF_RATE) && (k++ < 1000)); 325 301 cphy_override_rx_mode(sata_port, 3); 302 + cphy_override_tx_attenuation(sata_port, port_data[sata_port].tx_atten); 326 303 } 327 304 328 305 static int highbank_initialize_phys(struct device *dev, void __iomem *addr) 329 306 { 330 307 struct device_node *sata_node = dev->of_node; 331 - int phy_count = 0, phy, port = 0; 308 + int phy_count = 0, phy, port = 0, i; 332 309 void __iomem *cphy_base[CPHY_PHY_COUNT]; 333 310 struct device_node *phy_nodes[CPHY_PHY_COUNT]; 311 + u32 tx_atten[CPHY_PORT_COUNT]; 312 + 334 313 memset(port_data, 0, sizeof(struct phy_lane_info) * CPHY_PORT_COUNT); 335 314 memset(phy_nodes, 0, sizeof(struct device_node*) * CPHY_PHY_COUNT); 315 + memset(tx_atten, 0xff, CPHY_PORT_COUNT); 336 316 337 317 do { 338 318 u32 tmp; ··· 364 336 of_node_put(phy_data.np); 365 337 port += 1; 366 338 } while (port < CPHY_PORT_COUNT); 339 + of_property_read_u32_array(sata_node, "calxeda,tx-atten", 340 + tx_atten, port); 341 + for (i = 0; i < port; i++) 342 + port_data[i].tx_atten = (u8) tx_atten[i]; 367 343 return 0; 368 344 } 369 345