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/msc.h> 25 #include <l4/re/c/dma_space.h> 26 #include <l4/sys/types.h> 27 #include <stdint.h> 28 29 30 31 #ifdef __cplusplus 32 33 #include <l4/devices/hw_mmio_register_block.h> 34 35 36 37 // MMC/SD controller channel. 38 39 class Msc_channel 40 { 41 protected: 42 l4_addr_t _msc_start; 43 Hw::Register_block<32> _regs; 44 l4_cap_idx_t _irq; 45 46 // Support eight cards. 47 48 struct msc_card _cards[8]; 49 uint8_t _num_cards; 50 int _card; 51 52 // Utility methods. 53 54 uint32_t get_field(uint32_t reg, uint32_t mask, uint8_t shift); 55 void set_field(uint32_t reg, uint32_t mask, uint8_t shift, uint32_t value); 56 57 // Low-level operations. 58 59 void ack_irq(uint32_t flags); 60 void unmask_irq(uint32_t flags); 61 void reset(); 62 void start_clock(); 63 void stop_clock(); 64 65 // Command properties. 66 67 bool command_will_write(uint8_t index); 68 bool command_with_data(uint8_t index); 69 bool command_uses_busy(uint8_t index); 70 uint8_t get_response_format(uint8_t index); 71 72 bool app_command_will_write(uint8_t index); 73 bool app_command_with_data(uint8_t index); 74 bool app_command_uses_busy(uint8_t index); 75 uint8_t get_app_response_format(uint8_t index); 76 77 // Command initiation. 78 79 bool send_app_command(uint8_t index, uint32_t arg); 80 bool send_command(uint8_t index, uint32_t arg); 81 bool send_command(uint8_t index, uint32_t arg, uint8_t response_format, 82 bool data, bool write, bool busy); 83 84 // Response handling. 85 86 bool have_response(); 87 void read_response(uint16_t *buffer, uint8_t units); 88 bool wait_for_irq(uint32_t flags); 89 bool wait_for_irq(uint32_t flags, unsigned int timeout); 90 91 // Initialisation operations. 92 93 bool check_sd(); 94 void init_sdio(); 95 void init_sdmem(); 96 void init_mmc(); 97 void identify_cards(); 98 void query_cards(); 99 100 // Transfer operations. 101 102 uint32_t recv_data(l4re_dma_space_dma_addr_t paddr, uint32_t count); 103 uint32_t send_data(l4re_dma_space_dma_addr_t paddr, uint32_t count); 104 105 virtual uint32_t transfer(l4re_dma_space_dma_addr_t from_paddr, 106 l4re_dma_space_dma_addr_t to_paddr, 107 bool recv, uint32_t count) = 0; 108 109 public: 110 explicit Msc_channel(l4_addr_t msc_start, l4_addr_t start, l4_cap_idx_t irq); 111 112 virtual ~Msc_channel(); 113 114 void enable(); 115 116 msc_card *get_cards(); 117 118 uint8_t num_cards(); 119 120 uint32_t read_blocks(uint8_t card, l4re_dma_space_dma_addr_t paddr, 121 uint32_t block_address, uint32_t block_count); 122 }; 123 124 125 126 // MMC/SD controller device control. 127 128 class Msc_chip 129 { 130 protected: 131 l4_addr_t _msc_start, _start, _end; 132 133 virtual unsigned int num_channels() = 0; 134 135 public: 136 explicit Msc_chip(l4_addr_t msc_start, l4_addr_t start, l4_addr_t end); 137 }; 138 139 #endif /* __cplusplus */