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

pcmcia: Implement CLKRUN protocol disabling for Ricoh bridges

Currently, "disable_clkrun" yenta_socket module parameter is only
implemented for TI CardBus bridges.
Add also an implementation for Ricoh bridges that have the necessary
setting documented in publicly available datasheets.

Tested on a RL5C476II with a Sunrich C-160 CardBus NIC that doesn't work
correctly unless the CLKRUN protocol is disabled.

Let's also make it clear in its description that the "disable_clkrun"
module parameter only works on these two previously mentioned brands of
CardBus bridges.

Signed-off-by: Maciej S. Szmigiero <mail@maciej.szmigiero.name>
Cc: stable@vger.kernel.org
Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>

authored by

Maciej S. Szmigiero and committed by
Dominik Brodowski
95691e3e 1b22dcf6

+37 -1
+35
drivers/pcmcia/ricoh.h
··· 119 119 #define RL5C4XX_MISC_CONTROL 0x2F /* 8 bit */ 120 120 #define RL5C4XX_ZV_ENABLE 0x08 121 121 122 + /* Misc Control 3 Register */ 123 + #define RL5C4XX_MISC3 0x00A2 /* 16 bit */ 124 + #define RL5C47X_MISC3_CB_CLKRUN_DIS BIT(1) 125 + 122 126 #ifdef __YENTA_H 123 127 124 128 #define rl_misc(socket) ((socket)->private[0]) ··· 160 156 } 161 157 } 162 158 159 + static void ricoh_set_clkrun(struct yenta_socket *socket, bool quiet) 160 + { 161 + u16 misc3; 162 + 163 + /* 164 + * RL5C475II likely has this setting, too, however no datasheet 165 + * is publicly available for this chip 166 + */ 167 + if (socket->dev->device != PCI_DEVICE_ID_RICOH_RL5C476 && 168 + socket->dev->device != PCI_DEVICE_ID_RICOH_RL5C478) 169 + return; 170 + 171 + if (socket->dev->revision < 0x80) 172 + return; 173 + 174 + misc3 = config_readw(socket, RL5C4XX_MISC3); 175 + if (misc3 & RL5C47X_MISC3_CB_CLKRUN_DIS) { 176 + if (!quiet) 177 + dev_dbg(&socket->dev->dev, 178 + "CLKRUN feature already disabled\n"); 179 + } else if (disable_clkrun) { 180 + if (!quiet) 181 + dev_info(&socket->dev->dev, 182 + "Disabling CLKRUN feature\n"); 183 + misc3 |= RL5C47X_MISC3_CB_CLKRUN_DIS; 184 + config_writew(socket, RL5C4XX_MISC3, misc3); 185 + } 186 + } 187 + 163 188 static void ricoh_save_state(struct yenta_socket *socket) 164 189 { 165 190 rl_misc(socket) = config_readw(socket, RL5C4XX_MISC); ··· 205 172 config_writew(socket, RL5C4XX_16BIT_IO_0, rl_io(socket)); 206 173 config_writew(socket, RL5C4XX_16BIT_MEM_0, rl_mem(socket)); 207 174 config_writew(socket, RL5C4XX_CONFIG, rl_config(socket)); 175 + ricoh_set_clkrun(socket, true); 208 176 } 209 177 210 178 ··· 231 197 config_writew(socket, RL5C4XX_CONFIG, config); 232 198 233 199 ricoh_set_zv(socket); 200 + ricoh_set_clkrun(socket, false); 234 201 235 202 return 0; 236 203 }
+2 -1
drivers/pcmcia/yenta_socket.c
··· 26 26 27 27 static bool disable_clkrun; 28 28 module_param(disable_clkrun, bool, 0444); 29 - MODULE_PARM_DESC(disable_clkrun, "If PC card doesn't function properly, please try this option"); 29 + MODULE_PARM_DESC(disable_clkrun, 30 + "If PC card doesn't function properly, please try this option (TI and Ricoh bridges only)"); 30 31 31 32 static bool isa_probe = 1; 32 33 module_param(isa_probe, bool, 0444);