.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * FSI core driver |
---|
3 | 4 | * |
---|
4 | 5 | * Copyright (C) IBM Corporation 2016 |
---|
5 | | - * |
---|
6 | | - * This program is free software; you can redistribute it and/or modify |
---|
7 | | - * it under the terms of the GNU General Public License version 2 as |
---|
8 | | - * published by the Free Software Foundation. |
---|
9 | | - * |
---|
10 | | - * This program is distributed in the hope that it will be useful, |
---|
11 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
12 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
13 | | - * GNU General Public License for more details. |
---|
14 | 6 | * |
---|
15 | 7 | * TODO: |
---|
16 | 8 | * - Rework topology |
---|
.. | .. |
---|
58 | 50 | #define FSI_SMODE 0x0 /* R/W: Mode register */ |
---|
59 | 51 | #define FSI_SISC 0x8 /* R/W: Interrupt condition */ |
---|
60 | 52 | #define FSI_SSTAT 0x14 /* R : Slave status */ |
---|
| 53 | +#define FSI_SLBUS 0x30 /* W : LBUS Ownership */ |
---|
61 | 54 | #define FSI_LLMODE 0x100 /* R/W: Link layer mode register */ |
---|
62 | 55 | |
---|
63 | 56 | /* |
---|
.. | .. |
---|
73 | 66 | #define FSI_SMODE_SD_MASK 0xf /* Send delay mask */ |
---|
74 | 67 | #define FSI_SMODE_LBCRR_SHIFT 8 /* Clk ratio shift */ |
---|
75 | 68 | #define FSI_SMODE_LBCRR_MASK 0xf /* Clk ratio mask */ |
---|
| 69 | + |
---|
| 70 | +/* |
---|
| 71 | + * SLBUS fields |
---|
| 72 | + */ |
---|
| 73 | +#define FSI_SLBUS_FORCE 0x80000000 /* Force LBUS ownership */ |
---|
76 | 74 | |
---|
77 | 75 | /* |
---|
78 | 76 | * LLMODE fields |
---|
.. | .. |
---|
989 | 987 | uint32_t cfam_id; |
---|
990 | 988 | struct fsi_slave *slave; |
---|
991 | 989 | uint8_t crc; |
---|
992 | | - __be32 data, llmode; |
---|
| 990 | + __be32 data, llmode, slbus; |
---|
993 | 991 | int rc; |
---|
994 | 992 | |
---|
995 | 993 | /* Currently, we only support single slaves on a link, and use the |
---|
.. | .. |
---|
1059 | 1057 | slave->chip_id = prop; |
---|
1060 | 1058 | |
---|
1061 | 1059 | } |
---|
| 1060 | + |
---|
| 1061 | + slbus = cpu_to_be32(FSI_SLBUS_FORCE); |
---|
| 1062 | + rc = fsi_master_write(master, link, id, FSI_SLAVE_BASE + FSI_SLBUS, |
---|
| 1063 | + &slbus, sizeof(slbus)); |
---|
| 1064 | + if (rc) |
---|
| 1065 | + dev_warn(&master->dev, |
---|
| 1066 | + "can't set slbus on slave:%02x:%02x %d\n", link, id, |
---|
| 1067 | + rc); |
---|
1062 | 1068 | |
---|
1063 | 1069 | rc = fsi_slave_set_smode(slave); |
---|
1064 | 1070 | if (rc) { |
---|
.. | .. |
---|
1162 | 1168 | return rc; |
---|
1163 | 1169 | } |
---|
1164 | 1170 | |
---|
| 1171 | +static int fsi_master_link_disable(struct fsi_master *master, int link) |
---|
| 1172 | +{ |
---|
| 1173 | + if (master->link_enable) |
---|
| 1174 | + return master->link_enable(master, link, false); |
---|
| 1175 | + |
---|
| 1176 | + return 0; |
---|
| 1177 | +} |
---|
| 1178 | + |
---|
1165 | 1179 | static int fsi_master_link_enable(struct fsi_master *master, int link) |
---|
1166 | 1180 | { |
---|
1167 | 1181 | if (master->link_enable) |
---|
1168 | | - return master->link_enable(master, link); |
---|
| 1182 | + return master->link_enable(master, link, true); |
---|
1169 | 1183 | |
---|
1170 | 1184 | return 0; |
---|
1171 | 1185 | } |
---|
.. | .. |
---|
1200 | 1214 | } |
---|
1201 | 1215 | rc = fsi_master_break(master, link); |
---|
1202 | 1216 | if (rc) { |
---|
| 1217 | + fsi_master_link_disable(master, link); |
---|
1203 | 1218 | dev_dbg(&master->dev, |
---|
1204 | 1219 | "break to link %d failed: %d\n", link, rc); |
---|
1205 | 1220 | continue; |
---|
1206 | 1221 | } |
---|
1207 | 1222 | |
---|
1208 | | - fsi_slave_init(master, link, 0); |
---|
| 1223 | + rc = fsi_slave_init(master, link, 0); |
---|
| 1224 | + if (rc) |
---|
| 1225 | + fsi_master_link_disable(master, link); |
---|
1209 | 1226 | } |
---|
1210 | 1227 | |
---|
1211 | 1228 | return 0; |
---|
.. | .. |
---|
1272 | 1289 | |
---|
1273 | 1290 | static DEVICE_ATTR(break, 0200, NULL, master_break_store); |
---|
1274 | 1291 | |
---|
| 1292 | +static struct attribute *master_attrs[] = { |
---|
| 1293 | + &dev_attr_break.attr, |
---|
| 1294 | + &dev_attr_rescan.attr, |
---|
| 1295 | + NULL |
---|
| 1296 | +}; |
---|
| 1297 | + |
---|
| 1298 | +ATTRIBUTE_GROUPS(master); |
---|
| 1299 | + |
---|
| 1300 | +static struct class fsi_master_class = { |
---|
| 1301 | + .name = "fsi-master", |
---|
| 1302 | + .dev_groups = master_groups, |
---|
| 1303 | +}; |
---|
| 1304 | + |
---|
1275 | 1305 | int fsi_master_register(struct fsi_master *master) |
---|
1276 | 1306 | { |
---|
1277 | 1307 | int rc; |
---|
.. | .. |
---|
1279 | 1309 | |
---|
1280 | 1310 | mutex_init(&master->scan_lock); |
---|
1281 | 1311 | master->idx = ida_simple_get(&master_ida, 0, INT_MAX, GFP_KERNEL); |
---|
| 1312 | + if (master->idx < 0) |
---|
| 1313 | + return master->idx; |
---|
| 1314 | + |
---|
1282 | 1315 | dev_set_name(&master->dev, "fsi%d", master->idx); |
---|
| 1316 | + master->dev.class = &fsi_master_class; |
---|
1283 | 1317 | |
---|
1284 | 1318 | rc = device_register(&master->dev); |
---|
1285 | 1319 | if (rc) { |
---|
1286 | | - ida_simple_remove(&master_ida, master->idx); |
---|
1287 | | - return rc; |
---|
1288 | | - } |
---|
1289 | | - |
---|
1290 | | - rc = device_create_file(&master->dev, &dev_attr_rescan); |
---|
1291 | | - if (rc) { |
---|
1292 | | - device_del(&master->dev); |
---|
1293 | | - ida_simple_remove(&master_ida, master->idx); |
---|
1294 | | - return rc; |
---|
1295 | | - } |
---|
1296 | | - |
---|
1297 | | - rc = device_create_file(&master->dev, &dev_attr_break); |
---|
1298 | | - if (rc) { |
---|
1299 | | - device_del(&master->dev); |
---|
1300 | 1320 | ida_simple_remove(&master_ida, master->idx); |
---|
1301 | 1321 | return rc; |
---|
1302 | 1322 | } |
---|
.. | .. |
---|
1381 | 1401 | rc = bus_register(&fsi_bus_type); |
---|
1382 | 1402 | if (rc) |
---|
1383 | 1403 | goto fail_bus; |
---|
| 1404 | + |
---|
| 1405 | + rc = class_register(&fsi_master_class); |
---|
| 1406 | + if (rc) |
---|
| 1407 | + goto fail_class; |
---|
| 1408 | + |
---|
1384 | 1409 | return 0; |
---|
1385 | 1410 | |
---|
| 1411 | + fail_class: |
---|
| 1412 | + bus_unregister(&fsi_bus_type); |
---|
1386 | 1413 | fail_bus: |
---|
1387 | 1414 | unregister_chrdev_region(fsi_base_dev, FSI_CHAR_MAX_DEVICES); |
---|
1388 | 1415 | return rc; |
---|
.. | .. |
---|
1391 | 1418 | |
---|
1392 | 1419 | static void fsi_exit(void) |
---|
1393 | 1420 | { |
---|
| 1421 | + class_unregister(&fsi_master_class); |
---|
1394 | 1422 | bus_unregister(&fsi_bus_type); |
---|
1395 | 1423 | unregister_chrdev_region(fsi_base_dev, FSI_CHAR_MAX_DEVICES); |
---|
1396 | 1424 | ida_destroy(&fsi_minor_ida); |
---|