1 /* 2 * MSC (MMC/SD controller) peripheral support. 3 * 4 * Copyright (C) 2024 Paul Boddie <paul@boddie.org.uk> 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License as 8 * published by the Free Software Foundation; either version 2 of 9 * the License, or (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, 19 * Boston, MA 02110-1301, USA 20 */ 21 22 #pragma once 23 24 #include <l4/devices/clocks.h> 25 #include <l4/devices/cpm-generic.h> 26 #include <l4/devices/dma.h> 27 #include <l4/devices/dma-generic.h> 28 #include <l4/devices/msc.h> 29 #include <l4/sys/types.h> 30 #include <stdint.h> 31 32 33 34 #ifdef __cplusplus 35 36 #include <l4/devices/hw_mmio_register_block.h> 37 38 39 40 // MMC/SD controller channel. 41 42 class Msc_channel 43 { 44 protected: 45 l4_addr_t _msc_start; 46 Hw::Register_block<32> _regs; 47 l4_cap_idx_t _irq; 48 Cpm_chip *_cpm; 49 enum Clock_identifiers _clock; 50 51 // Support eight cards. 52 53 struct msc_card _cards[8]; 54 uint8_t _num_cards; 55 int _card; 56 57 // Utility methods. 58 59 uint32_t get_field(uint32_t reg, uint32_t mask, uint8_t shift); 60 void set_field(uint32_t reg, uint32_t mask, uint8_t shift, uint32_t value); 61 62 // Low-level operations. 63 64 void ack_irq(uint32_t flags); 65 void unmask_irq(uint32_t flags); 66 67 virtual void reset(); 68 69 bool set_clock_frequency(uint64_t frequency); 70 void start_clock(); 71 void stop_clock(); 72 73 // Hardware properties. 74 75 virtual bool have_dma_enable_in_command(); 76 virtual bool have_dma_selection(); 77 78 // Command properties. 79 80 bool command_will_write(uint8_t index); 81 bool command_with_data(uint8_t index); 82 bool command_uses_busy(uint8_t index); 83 uint8_t get_response_format(uint8_t index); 84 85 bool app_command_will_write(uint8_t index); 86 bool app_command_with_data(uint8_t index); 87 bool app_command_uses_busy(uint8_t index); 88 uint8_t get_app_response_format(uint8_t index); 89 90 // Command initiation. 91 92 bool send_app_command(uint8_t index, uint32_t arg); 93 bool send_command(uint8_t index, uint32_t arg); 94 bool send_command(uint8_t index, uint32_t arg, uint8_t response_format, 95 bool data, bool write, bool busy); 96 97 // Response handling. 98 99 bool have_response(); 100 void read_response(uint16_t *buffer, uint8_t units); 101 bool wait_for_irq(uint32_t flags); 102 bool wait_for_irq(uint32_t flags, unsigned int timeout); 103 104 // Initialisation operations. 105 106 bool check_sd(); 107 void init_sdio(); 108 void init_sdmem(); 109 void init_mmc(); 110 void identify_cards(); 111 void query_cards(); 112 113 // Transfer operations. 114 115 uint32_t recv_data(struct dma_region *region, uint32_t count); 116 uint32_t send_data(struct dma_region *region, uint32_t count); 117 118 virtual uint32_t transfer(l4re_dma_space_dma_addr_t from_paddr, 119 l4re_dma_space_dma_addr_t to_paddr, 120 bool recv, uint32_t count) = 0; 121 122 public: 123 explicit Msc_channel(l4_addr_t msc_start, l4_addr_t start, l4_cap_idx_t irq, 124 Cpm_chip *cpm, enum Clock_identifiers clock); 125 126 virtual ~Msc_channel(); 127 128 void enable(); 129 130 msc_card *get_cards(); 131 132 uint8_t num_cards(); 133 134 uint32_t read(uint8_t card, struct dma_region *region, 135 uint32_t address, uint32_t count); 136 137 uint32_t read_blocks(uint8_t card, struct dma_region *region, 138 uint32_t block_address, uint32_t block_count); 139 }; 140 141 142 143 // MMC/SD controller device control. 144 145 class Msc_chip 146 { 147 protected: 148 l4_addr_t _msc_start, _start, _end; 149 Cpm_chip *_cpm; 150 151 virtual unsigned int num_channels() = 0; 152 153 public: 154 explicit Msc_chip(l4_addr_t msc_start, l4_addr_t start, l4_addr_t end, 155 Cpm_chip *cpm); 156 157 virtual Msc_channel *get_channel(uint8_t channel, l4_cap_idx_t irq, 158 Dma_channel *dma) = 0; 159 }; 160 161 Msc_chip *new_msc_chip(const char *name, l4_addr_t msc_start, l4_addr_t start, 162 l4_addr_t end, Cpm_chip *cpm); 163 164 #endif /* __cplusplus */