blob: dcb5fcf476b5323be89bce5fe0a1bf0109811011 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Simon Glass3665a402016-05-01 11:36:11 -06002/*
3 * Copyright (C) 2000-2005, DENX Software Engineering
4 * Wolfgang Denk <wd@denx.de>
5 * Copyright (C) Procsys. All rights reserved.
6 * Mushtaq Khan <mushtaq_k@procsys.com>
7 * <mushtaqk_921@yahoo.co.in>
8 * Copyright (C) 2008 Freescale Semiconductor, Inc.
9 * Dave Liu <daveliu@freescale.com>
Simon Glass3665a402016-05-01 11:36:11 -060010 */
11
12#include <common.h>
Simon Glass821bb522017-07-29 11:35:15 -060013#include <ahci.h>
Simon Glass655306c2020-05-10 11:39:58 -060014#include <blk.h>
Simon Glass7d741ac2016-05-01 11:36:26 -060015#include <dm.h>
Simon Glass655306c2020-05-10 11:39:58 -060016#include <part.h>
Simon Glass3665a402016-05-01 11:36:11 -060017#include <sata.h>
Tony Dinha87cbb82023-10-11 13:26:42 -070018#include <dm/device-internal.h>
19#include <dm/uclass-internal.h>
Simon Glass3665a402016-05-01 11:36:11 -060020
Simon Glass821bb522017-07-29 11:35:15 -060021#ifndef CONFIG_AHCI
Simon Glass3665a402016-05-01 11:36:11 -060022struct blk_desc sata_dev_desc[CONFIG_SYS_SATA_MAX_DEVICE];
Simon Glass821bb522017-07-29 11:35:15 -060023#endif
24
25int sata_reset(struct udevice *dev)
26{
27 struct ahci_ops *ops = ahci_get_ops(dev);
28
29 if (!ops->reset)
30 return -ENOSYS;
31
32 return ops->reset(dev);
33}
34
35int sata_dm_port_status(struct udevice *dev, int port)
36{
37 struct ahci_ops *ops = ahci_get_ops(dev);
38
39 if (!ops->port_status)
40 return -ENOSYS;
Simon Glass3665a402016-05-01 11:36:11 -060041
Simon Glass821bb522017-07-29 11:35:15 -060042 return ops->port_status(dev, port);
43}
44
45int sata_scan(struct udevice *dev)
46{
47 struct ahci_ops *ops = ahci_get_ops(dev);
48
49 if (!ops->scan)
50 return -ENOSYS;
51
52 return ops->scan(dev);
53}
54
Tony Dinha87cbb82023-10-11 13:26:42 -070055int sata_rescan(bool verbose)
56{
57 int ret;
58 struct udevice *dev;
59
60 if (verbose)
61 printf("Removing devices on SATA bus...\n");
62
63 blk_unbind_all(UCLASS_AHCI);
64
65 ret = uclass_find_first_device(UCLASS_AHCI, &dev);
66 if (ret || !dev) {
67 printf("Cannot find SATA device (err=%d)\n", ret);
68 return -ENOSYS;
69 }
70
71 ret = device_remove(dev, DM_REMOVE_NORMAL);
72 if (ret) {
73 printf("Cannot remove SATA device '%s' (err=%d)\n", dev->name, ret);
74 return -ENOSYS;
75 }
76
77 if (verbose)
78 printf("Rescanning SATA bus for devices...\n");
79
80 ret = uclass_probe_all(UCLASS_AHCI);
81
Tony Dinhe240edf2023-10-06 20:34:28 -070082 if (ret == -ENODEV) {
83 if (verbose)
84 printf("No SATA block device found\n");
85 return 0;
86 }
87
Tony Dinha87cbb82023-10-11 13:26:42 -070088 return ret;
89}
90
Simon Glass821bb522017-07-29 11:35:15 -060091#ifndef CONFIG_AHCI
Simon Glass3665a402016-05-01 11:36:11 -060092#ifdef CONFIG_PARTITIONS
93struct blk_desc *sata_get_dev(int dev)
94{
95 return (dev < CONFIG_SYS_SATA_MAX_DEVICE) ? &sata_dev_desc[dev] : NULL;
96}
97#endif
Simon Glass821bb522017-07-29 11:35:15 -060098#endif
Simon Glass3665a402016-05-01 11:36:11 -060099
Simon Glass7d741ac2016-05-01 11:36:26 -0600100static unsigned long sata_bread(struct udevice *dev, lbaint_t start,
101 lbaint_t blkcnt, void *dst)
102{
103 return -ENOSYS;
104}
105
106static unsigned long sata_bwrite(struct udevice *dev, lbaint_t start,
107 lbaint_t blkcnt, const void *buffer)
108{
109 return -ENOSYS;
110}
Simon Glass3665a402016-05-01 11:36:11 -0600111
Simon Glass821bb522017-07-29 11:35:15 -0600112#ifndef CONFIG_AHCI
Simon Glass3665a402016-05-01 11:36:11 -0600113int __sata_initialize(void)
114{
Tang Yuantianb450f932016-11-21 10:24:20 +0800115 int rc, ret = -1;
Simon Glass3665a402016-05-01 11:36:11 -0600116 int i;
117
118 for (i = 0; i < CONFIG_SYS_SATA_MAX_DEVICE; i++) {
119 memset(&sata_dev_desc[i], 0, sizeof(struct blk_desc));
Simon Glassfada3f92022-09-17 09:00:09 -0600120 sata_dev_desc[i].uclass_id = UCLASS_AHCI;
Simon Glass3665a402016-05-01 11:36:11 -0600121 sata_dev_desc[i].devnum = i;
122 sata_dev_desc[i].part_type = PART_TYPE_UNKNOWN;
123 sata_dev_desc[i].type = DEV_TYPE_HARDDISK;
124 sata_dev_desc[i].lba = 0;
125 sata_dev_desc[i].blksz = 512;
126 sata_dev_desc[i].log2blksz = LOG2(sata_dev_desc[i].blksz);
Simon Glass3665a402016-05-01 11:36:11 -0600127 rc = init_sata(i);
128 if (!rc) {
129 rc = scan_sata(i);
130 if (!rc && sata_dev_desc[i].lba > 0 &&
Tang Yuantianb450f932016-11-21 10:24:20 +0800131 sata_dev_desc[i].blksz > 0) {
Simon Glass3665a402016-05-01 11:36:11 -0600132 part_init(&sata_dev_desc[i]);
Tang Yuantianb450f932016-11-21 10:24:20 +0800133 ret = i;
134 }
Simon Glass3665a402016-05-01 11:36:11 -0600135 }
136 }
137
Tang Yuantianb450f932016-11-21 10:24:20 +0800138 return ret;
Simon Glass3665a402016-05-01 11:36:11 -0600139}
140int sata_initialize(void) __attribute__((weak, alias("__sata_initialize")));
141
142__weak int __sata_stop(void)
143{
144 int i, err = 0;
145
146 for (i = 0; i < CONFIG_SYS_SATA_MAX_DEVICE; i++)
147 err |= reset_sata(i);
148
149 if (err)
150 printf("Could not reset some SATA devices\n");
151
152 return err;
153}
154int sata_stop(void) __attribute__((weak, alias("__sata_stop")));
Simon Glass821bb522017-07-29 11:35:15 -0600155#endif
Simon Glass3665a402016-05-01 11:36:11 -0600156
Simon Glass7d741ac2016-05-01 11:36:26 -0600157static const struct blk_ops sata_blk_ops = {
158 .read = sata_bread,
159 .write = sata_bwrite,
160};
161
162U_BOOT_DRIVER(sata_blk) = {
163 .name = "sata_blk",
164 .id = UCLASS_BLK,
165 .ops = &sata_blk_ops,
166};